搜索

保护 OpenShift Pipelines

download PDF
Red Hat OpenShift Pipelines 1.13

OpenShift Pipelines 的安全功能

Red Hat OpenShift Documentation Team

摘要

本文档提供有关 OpenShift Pipelines 的安全功能的信息。

第 1 章 为 OpenShift Pipelines 提供链安全使用 Tekton 链

Tekton Chains 是一个 Kubernetes 自定义资源定义(CRD)控制器。您可以使用它来管理使用 Red Hat OpenShift Pipelines 创建的任务和管道的供应链安全。

默认情况下,Tekton Chains 会观察 OpenShift Container Platform 集群中的所有任务运行执行。当任务运行完成时,Tekton Chains 会获取任务运行的快照。然后,它会将快照转换为一个或多个标准有效负载格式,最后签署并存储所有工件。

要捕获有关任务运行的信息,Tekton Chains 使用 Result 对象。当对象不可用时,Tekton 会链 OCI 镜像的 URL 和合格摘要。

1.1. 主要特性

  • 您可以使用如 cosignskopeo 等加密密钥为任务运行、任务运行结果和 OCI registry 镜像签名。
  • 您可以使用"测试"格式,如 in-toto
  • 您可以使用 OCI 存储库作为存储后端安全存储签名和签名工件。

1.2. 配置 Tekton 链

Red Hat OpenShift Pipelines Operator 默认安装 Tekton 链。您可以通过修改 TektonConfig 自定义资源来配置 Tekton 链;Operator 会自动应用您在此自定义资源中所做的更改。

要编辑自定义资源,请使用以下命令:

$ oc edit TektonConfig config

自定义资源包含一个 chain: 数组。您可以在这个阵列中添加任何支持的配置参数,如下例所示:

apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: config
spec:
  addon: {}
  chain:
    artifacts.taskrun.format: tekton
  config: {}

1.2.1. Tekton Chains 配置支持的参数

集群管理员可以使用各种支持的参数键和值来配置任务运行、OCI 镜像和存储的规格。

1.2.1.1. 任务运行工件支持的参数
表 1.1. 链配置:任务运行工件支持的参数
描述支持的值默认值

artifacts.taskrun.format

存储任务运行有效负载的格式。

in-toto, slsa/v1

in-toto

artifacts.taskrun.storage

任务运行签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 “tekton,oci”。要禁用存储任务运行工件,请提供空字符串 ""

tekton, oci, gcs, docdb, grafeas

tekton

artifacts.taskrun.signer

用于签名任务运行有效负载的签名后端。

x509,kms

x509

注意

slsa/v1in-toto 的别名,用于向后兼容。

1.2.1.2. 管道运行工件支持的参数
表 1.2. 链配置:管道运行工件支持的参数
参数描述支持的值默认值

artifacts.pipelinerun.format

存储管道运行有效负载的格式。

in-toto, slsa/v1

in-toto

artifacts.pipelinerun.storage

用于存储管道运行签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 “tekton,oci”。要禁用存储管道运行工件,请提供一个空字符串 ""

tekton, oci, gcs, docdb, grafeas

tekton

artifacts.pipelinerun.signer

用于签名管道运行有效负载的签名后端。

x509,kms

x509

注意
  • slsa/v1in-toto 的别名,用于向后兼容。
  • 对于 grafeas 存储后端,只支持 Container Analysis。您无法在 Tekton 链的当前版本中配置 grafeas 服务器地址。
1.2.1.3. OCI 工件支持的参数
表 1.3. 链配置: OCI 工件支持的参数
参数描述支持的值默认值

artifacts.oci.format

存储 OCI 有效负载的格式。

simplesigning

simplesigning

artifacts.oci.storage

用于存储 OCI 签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 “oci,tekton”。要禁用存储 OCI 工件,请提供一个空字符串 ""

tekton, oci, gcs, docdb, grafeas

oci

artifacts.oci.signer

用于签名 OCI 有效负载的签名后端。

x509,kms

x509

1.2.1.4. KMS 符号支持的参数
表 1.4. 链配置: KMS 符号支持的参数
参数描述支持的值默认值

signers.kms.kmsref

对要在 kms 符号器中使用的 KMS 服务的 URI 引用。

支持的方案:gcpkms://, awskms://, azurekms://, hashivault://.如需了解更多详细信息,请参阅 Sigstore 文档中的 KMS 支持

 
1.2.1.5. 支持的存储参数
表 1.5. 链配置:存储支持的参数
参数描述支持的值默认值

storage.gcs.bucket

存储的 GCS 存储桶

  

storage.oci.repository

用于存储 OCI 签名和测试的 OCI 存储库。

如果您将其中一个工件存储后端配置为 oci,且没有定义此密钥,Tekton Chains 会将 attestation 与存储的 OCI 工件本身一起存储。如果您定义了这个密钥,则 attestation 不会与 OCI 工件一起存储,而是存储在指定的位置。如需更多信息,请参阅 cosign 文档

 

builder.id

为 in-toto attestations 设置的构建器 ID

 

https://tekton.dev/chains/v2

如果您启用了 docdb 存储方法用于任何工件,请配置 docstore 存储选项。有关 go-cloud docstore URI 格式的更多信息,请参阅文档 存储软件包文档。Red Hat OpenShift Pipelines 支持以下 docstore 服务:

  • firestore
  • dynamodb
表 1.6. 链配置:docstore 存储支持的参数
参数描述支持的值默认值

storage.docdb.url

docstore 集合的 go-cloud URI 引用。在为任何工件启用了 docdb 存储方法时使用。

firestore://projects/[PROJECT]/databases/(default)/documents/[COLLECTION]?name_field=name

 

如果您为任何工件启用 grafeas 存储方法,请配置 Grafeas 存储选项。有关 Grafeas 备注和发生的更多信息,请参阅 Grafeas 概念

要创建并行,Red Hat OpenShift Pipelines 必须首先创建用于链接并行的备注。Red Hat OpenShift Pipelines 创建两种类型的发生: ATTESTATION Occurrence 和 BUILD Occurrence。

Red Hat OpenShift Pipelines 使用可配置的 noteid 作为备注名称的前缀。它附加 ATTESTATION 备注的后缀 -simplesigning,以及 BUILD 备注的后缀 -intoto。如果没有配置 noteid 字段,Red Hat OpenShift Pipelines 将使用 tekton-<NAMESPACE> 作为前缀。

表 1.7. 链配置:Grafeas 存储支持的参数
参数描述支持的值默认值

storage.grafeas.projectid

Grafeas 服务器用于存储发生的 OpenShift Container Platform 项目。

  

storage.grafeas.noteid

可选:用于所有创建备注的名称的前缀。

没有空格的字符串。

 

storage.grafeas.notehint

可选:Grafeas ATTESTATION 备注的 human_readable_name 字段。

 

此 attestation 备注由 Tekton 链生成

另外,您还可以在测试时启用额外的二进制透明度上传。

表 1.8. 链配置:支持参数,以获得透明测试存储
参数描述支持的值默认值

transparency.enabled

启用或禁用自动二进制透明度上传。

true,false,manual

false

transparency.url

如果启用,用于上传二进制透明度的 URL。

 

https://rekor.sigstore.dev

注意

如果将 transparency.enabled 设置为 manual,则只有带有以下注解的任务和管道运行上传到透明度日志中:

chains.tekton.dev/transparency-upload: "true"

如果配置 x509 签名后端,您可以选择使用 Fulcio 启用无密钥签名。

表 1.9. 链配置:使用 Fulcio 进行 x509 密钥无密钥签名的支持参数
参数描述支持的值默认值

signers.x509.fulcio.enabled

从 Fulcio 启用或禁用请求自动证书。

true, false

false

signers.x509.fulcio.address

请求证书的 Fulcio 地址(如果启用)。

 

https://v1.fulcio.sigstore.dev

signers.x509.fulcio.issuer

预期的 OIDC 签发者。

 

https://oauth2.sigstore.dev/auth

signers.x509.fulcio.provider

从中请求 ID 令牌的供应商。

Google,spiffe,github,filesystem

Red Hat OpenShift Pipelines 会尝试使用每个供应商

signers.x509.identity.token.file

包含 ID 令牌的文件的路径。

  

signers.x509.tuf.mirror.url

TUF 服务器的 URL。必须存在 $TUF_URL/root.json

 

https://sigstore-tuf-root.storage.googleapis.com

如果您配置 kms 签名后端,请根据需要设置 KMS 配置,包括 OIDC 和 Spire。

表 1.10. 链配置: KMS 签名支持的参数
参数描述支持的值默认值

signers.kms.auth.address

KMS 服务器的 URI (VAULT_ADDR 的值)。

signers.kms.auth.token

KMS 服务器的身份验证令牌 (VAULT_TOKEN 值)。

signers.kms.auth.oidc.path

OIDC 身份验证的路径(例如,Vault 为 jwt)。

signers.kms.auth.oidc.role

OIDC 身份验证的角色。

signers.kms.auth.spire.sock

KMS 令牌的 Spire 套接字的 URI (例如:unix:///tmp/spire-agent/public/api.sock)。

signers.kms.auth.spire.audience

从 Spire 请求 SVID 的受众。

1.3. 在 Tekton Chains 中签名数据的 secret

集群管理员可以生成密钥对,并使用 Tekton 链来使用 Kubernetes secret 为工件签名。要使 Tekton 链正常工作,加密的密钥和密码必须存在,作为 openshift-pipelines 命名空间中的 signing-secrets secret 的一部分。

目前,Tekton 链支持 x509cosign 签名方案。

注意

只使用一个受支持的签名方案。

要将 x509 签名方案与 Tekton Chains 搭配使用,请将 ed25519ecdsa 类型的 x509.pem 私钥存储在 signing-secrets Kubernetes secret 中。

1.3.1. 使用 cosign 进行签名

您可以使用 cosign 工具使用带有 Tekton 链的 cosign 签名方案。

先决条件

流程

  1. 运行以下命令,生成 cosign.keycosign.pub 密钥对:

    $ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets

    Cosign 会提示您输入密码,然后创建一个 Kubernetes secret。

  2. 将加密的 cosign.key 私钥和 cosign.password 解密密码存储在 signing-secrets Kubernetes secret 中。确保私钥存储为 ENCRYPTED COSIGN PRIVATE KEY 类型的加密 PEM 文件。

1.3.2. 使用 skopeo 进行签名

您可以使用 skopeo 工具生成密钥,并在带有 Tekton 链的 cosign 签名方案中使用它们。

先决条件

流程

  1. 运行以下命令生成公钥/私钥对:

    $ skopeo generate-sigstore-key --output-prefix <mykey> 1
    1
    <mykey> 替换为您选择的密钥名称。

    Skopeo 会提示您输入私钥的密码短语,然后创建名为 <mykey>.private<mykey>.pub 的密钥文件。

  2. 运行以下命令,使用 base64 工具对 <mykey>.pub 文件进行编码:

    $ base64 -w 0 <mykey>.pub > b64.pub
  3. 运行以下命令,使用 base64 工具对 <mykey>.private 文件进行编码:

    $ base64 -w 0 <mykey>.private > b64.private
  4. 运行以下命令,使用 base64 工具对 passhprase 进行编码:

    $ echo -n '<passphrase>' | base64 -w 0 > b64.passphrase 1
    1
    <passphrase> 替换为用于密钥对的密码短语。
  5. 运行以下命令,在 openshift-pipelines 命名空间中创建 signing-secrets secret:

    $ oc create secret generic signing-secrets -n openshift-pipelines
  6. 运行以下命令来编辑 signing-secrets secret:

    $ oc edit secret -n openshift-pipelines signing-secrets

    使用以下方法在 secret 的数据中添加编码的密钥:

    apiVersion: v1
    data:
      cosign.key: <Encoded <mykey>.private> 1
      cosign.password: <Encoded passphrase> 2
      cosign.pub: <Encoded <mykey>.pub> 3
    immutable: true
    kind: Secret
    metadata:
      name: signing-secrets
    # ...
    type: Opaque
    1
    <Encoded <mykey>.private> 替换为 b64.private 文件的内容。
    2
    <Encoded passphrase> 替换为 b64.passphrase 文件的内容。
    3
    <Encoded <mykey>.pub> 替换为 b64.pub 文件的内容。

1.3.3. 解决 "secret already exists" 错误

如果 signing-secret secret 已经填充,则创建此 secret 的命令可能会输出以下出错信息:

Error from server (AlreadyExists): secrets "signing-secrets" already exists

您可以通过删除 secret 来解决这个问题。

流程

  1. 运行以下命令来删除 signing-secret secret:

    $ oc delete secret signing-secrets -n openshift-pipelines
  2. 重新创建密钥对,并使用您首选的签名方案将其存储在机密中。

1.4. 对 OCI registry 进行身份验证

在将签名推送到 OCI Registry 之前,集群管理员必须配置 Tekton 链,以便与 registry 进行身份验证。Tekton Chains 控制器使用与任务运行相同的服务帐户。要设置具有所需凭证(push)到 OCI registry 的服务帐户,请执行以下步骤:

流程

  1. 设置 Kubernetes 服务帐户的命名空间和名称。

    $ export NAMESPACE=<namespace> 1
    $ export SERVICE_ACCOUNT_NAME=<service_account> 2
    1
    与服务帐户关联的命名空间。
    2
    服务帐户的名称。
  2. 创建 Kubernetes secret。

    $ oc create secret registry-credentials \
      --from-file=.dockerconfigjson \ 1
      --type=kubernetes.io/dockerconfigjson \
      -n $NAMESPACE
    1
    使用 Docker 配置文件的路径替换。默认路径为 ~/.docker/config.json
  3. 授予服务帐户对 secret 的访问权限。

    $ oc patch serviceaccount $SERVICE_ACCOUNT_NAME \
      -p "{\"imagePullSecrets\": [{\"name\": \"registry-credentials\"}]}" -n $NAMESPACE

    如果对 Red Hat OpenShift Pipelines 分配到所有任务的默认 pipeline 服务帐户进行补丁,Red Hat OpenShift Pipelines Operator 将覆盖服务帐户。作为最佳实践,您可以执行以下步骤:

    1. 创建单独的服务帐户,以分配给用户的任务运行。

      $ oc create serviceaccount <service_account_name>
    2. 通过设置任务运行模板中的 serviceaccountname 字段的值,将服务帐户关联到运行任务。

      apiVersion: tekton.dev/v1
      kind: TaskRun
      metadata:
        name: build-push-task-run-2
      spec:
        taskRunTemplate:
          serviceAccountName: build-bot 1
        taskRef:
          name: build-push
      ...
      1
      使用新创建的服务帐户的名称替换。

1.5. 创建和验证任务运行签名而无需任何其他身份验证

要验证使用 Tekton 链与任何其他身份验证一起运行的任务的签名,请执行以下任务:

  • 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。
  • 配置 Tekton Chains 后端存储。
  • 创建任务运行,为它签名并将签名和有效负载存储为任务运行自身时的注解。
  • 从已签名任务运行中检索签名和有效负载。
  • 验证任务运行的签名。

先决条件

确保在集群中安装了以下组件:

  • Red Hat OpenShift Pipelines Operator
  • Tekton Chains
  • Cosign

流程

  1. 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。有关创建密钥对并将其保存为 secret 的更多信息,请参阅 "Signing secrets in Tekton Chains"。
  2. 在 Tekton Chains 配置中,禁用 OCI 存储,并将任务运行存储和格式设置为 tekton。在 TektonConfig 自定义资源中设置以下值:

    apiVersion: operator.tekton.dev/v1alpha1
    kind: TektonConfig
    metadata:
      name: config
    spec:
    # ...
        chain:
          artifacts.oci.storage: ""
          artifacts.taskrun.format: tekton
          artifacts.taskrun.storage: tekton
    # ...

    有关使用 TektonConfig 自定义资源配置 Tekton 链的更多信息,请参阅"配置 Tekton 链"。

  3. 要重启 Tekton Chains 控制器以确保应用了修改后的配置,请输入以下命令:

    $ oc delete po -n openshift-pipelines -l app=tekton-chains-controller
  4. 输入以下命令来创建任务运行:

    $ oc create -f https://raw.githubusercontent.com/tektoncd/chains/main/examples/taskruns/task-output-image.yaml 1
    1
    将示例 URI 替换为指向任务运行的 URI 或文件路径。

    输出示例

    taskrun.tekton.dev/build-push-run-output-image-qbjvh created

  5. 输入以下命令来检查步骤的状态。等待进程完成。

    $ tkn tr describe --last

    输出示例

    [...truncated output...]
    NAME                            STATUS
    ∙ create-dir-builtimage-9467f   Completed
    ∙ git-source-sourcerepo-p2sk8   Completed
    ∙ build-and-push                Completed
    ∙ echo                          Completed
    ∙ image-digest-exporter-xlkn7   Completed

  6. 要从存储为 base64 编码注解的对象检索签名,请输入以下命令:

    $ tkn tr describe --last -o jsonpath="{.metadata.annotations.chains\.tekton\.dev/signature-taskrun-$TASKRUN_UID}" | base64 -d > sig
    $ export TASKRUN_UID=$(tkn tr describe --last -o  jsonpath='{.metadata.uid}')
  7. 要使用您创建的公钥验证签名,请输入以下命令:
$ cosign verify-blob-attestation --insecure-ignore-tlog --key path/to/cosign.pub --signature sig --type slsaprovenance --check-claims=false /dev/null 1
1
path/to/cosign.pub 替换为公钥文件的路径名。

输出示例

Verified OK

1.5.1. 其他资源

1.6. 使用 Tekton 链来签名和验证镜像并证明

集群管理员可以通过执行以下任务来使用 Tekton 链来签名和验证镜像和验证镜像:

  • 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。
  • 为 OCI registry 设置身份验证,以在测试过程中存储镜像、镜像签名和签名的镜像。
  • 配置 Tekton 链以生成和签署认可。
  • 在任务运行中,使用 Kaniko 创建镜像。
  • 验证已签名的镜像及已签名证明。

先决条件

确保在集群中安装了以下内容:

  • Red Hat OpenShift Pipelines Operator
  • Tekton Chains
  • Cosign
  • Rekor
  • jq

流程

  1. 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret:

    $ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets

    提示时提供密码。Cosign 将生成的私钥作为 openshift-pipelines 命名空间中的 signing-secrets Kubernetes secret 的一部分存储在 openshift-pipelines 命名空间中,并将公钥写入 cosign.pub 本地文件。

  2. 为镜像 registry 配置身份验证。

    1. 要将 Tekton Chains 控制器配置为将签名推送到 OCI registry,请使用与任务运行服务帐户关联的凭证。如需更多信息,请参阅"授权到 OCI registry"部分。
    2. 要为构建并推送到 registry 的 Kaniko 任务配置身份验证,请创建一个包含所需凭证的 docker config.json 文件的 Kubernetes secret。

      $ oc create secret generic <docker_config_secret_name> \ 1
        --from-file <path_to_config.json> 2
      1
      使用 docker config secret 的名称替换。
      2
      使用 docker config.json 文件的路径替换。
  3. 通过在 chains-config 对象中设置 artifacts.taskrun.formatartifacts.taskrun.storagetransparency.enabled 参数来配置 Tekton 链 :

    $ oc patch configmap chains-config -n openshift-pipelines -p='{"data":{"artifacts.taskrun.format": "in-toto"}}'
    
    $ oc patch configmap chains-config -n openshift-pipelines -p='{"data":{"artifacts.taskrun.storage": "oci"}}'
    
    $ oc patch configmap chains-config -n openshift-pipelines -p='{"data":{"transparency.enabled": "true"}}'
  4. 启动 Kaniko 任务。

    1. 将 Kaniko 任务应用到集群。

      $ oc apply -f examples/kaniko/kaniko.yaml 1
      1
      使用 Kaniko 任务的 URI 或文件路径替换。
    2. 设置适当的环境变量。

      $ export REGISTRY=<url_of_registry> 1
      
      $ export DOCKERCONFIG_SECRET_NAME=<name_of_the_secret_in_docker_config_json> 2
      1
      使用您要推送镜像的 registry 的 URL 替换。
      2
      使用 docker config.json 文件中的 secret 名称替换。
    3. 启动 Kaniko 任务。

      $ tkn task start --param IMAGE=$REGISTRY/kaniko-chains --use-param-defaults --workspace name=source,emptyDir="" --workspace name=dockerconfig,secret=$DOCKERCONFIG_SECRET_NAME kaniko-chains

      观察此任务的日志,直到所有步骤都完成。身份验证成功后,最终镜像将推送到 $REGISTRY/kaniko-chains

  5. 等待一分钟,以允许 Tekton 链生成证据并对其进行签名,然后在任务运行时检查 chains.tekton.dev/signed=true 注解的可用性。

    $ oc get tr <task_run_name> \ 1
    -o json | jq -r .metadata.annotations
    
    {
      "chains.tekton.dev/signed": "true",
      ...
    }
    1
    使用任务运行的名称替换。
  6. 验证镜像和 attestation。

    $ cosign verify --key cosign.pub $REGISTRY/kaniko-chains
    
    $ cosign verify-attestation --key cosign.pub $REGISTRY/kaniko-chains
  7. 在 Rekor 中找到镜像的验证情况。

    1. 获取 $REGISTRY/kaniko-chains 镜像摘要。您可以搜索任务运行或拉取镜像以提取摘要。
    2. 搜索 Rekor 以查找与镜像 sha256 摘要匹配的所有条目。

      $ rekor-cli search --sha <image_digest> 1
      
      <uuid_1> 2
      <uuid_2> 3
      ...
      1
      使用镜像的 sha256 摘要替换。
      2
      第一个匹配通用唯一标识符(UUID)。
      3
      第二个匹配 UUID。

      搜索结果显示匹配条目的 UUID。其中其中一个 UUID 包含 attestation。

    3. 检查 attestation。

      $ rekor-cli get --uuid <uuid> --format json | jq -r .Attestation | base64 --decode | jq

1.7. 其他资源

第 2 章 为 pod 配置安全上下文

OpenShift Pipelines 启动的 pod 的默认服务帐户是 管道。与 pipeline 服务帐户关联的安全性上下文约束(SCC)是 pipelines-sccpipelines-scc SCC 基于 anyuid SCC,但有以下 YAML 规范中定义的细微差别:

pipelines-scc.yaml 片断示例

apiVersion: security.openshift.io/v1
kind: SecurityContextConstraints
# ...
allowedCapabilities:
  - SETFCAP
# ...
fsGroup:
  type: MustRunAs
# ...

另外,Buildah 集群任务作为 OpenShift Pipelines 的一部分提供,使用 vfs 作为默认存储驱动程序。

您可以为 OpenShift Pipelines 为管道运行和任务运行创建的 pod 配置安全上下文。您可以进行以下更改:

  • 更改所有 Pod 的 default 和 maximum SCC
  • 更改为管道运行和在特定命名空间中运行的 Pod 的默认 SCC
  • 配置特定的管道运行或任务运行以使用自定义 SCC 和服务帐户
注意

运行 buildah 的最简单方法是,确保所有镜像都可以构建,以便在具有 特权 SCC 的 pod 中以 root 用户身份运行。有关运行带有更严格的安全设置的 buildah 的说明,请参阅 以非 root 用户身份使用 Buildah 构建容器镜像

2.1. 为 OpenShift Pipelines 创建的 pod 配置默认和最大 SCC

您可以为 OpenShift Pipelines 为任务运行和管道运行创建的所有 pod 配置默认安全性上下文约束(SCC)。您还可以配置最大 SCC,这是可在任意命名空间中为这些 pod 配置的最低限制 SCC。

流程

  • 输入以下命令编辑 TektonConfig 自定义资源(CR):

    $ oc edit TektonConfig config

    在 spec 中设置 default 和 maximum SCC,如下例所示:

    apiVersion: operator.tekton.dev/v1alpha1
    kind: TektonConfig
    metadata:
      name: config
    spec:
    #  ...
      platforms:
        openshift:
          scc:
            default: "restricted-v2" 1
            maxAllowed: "privileged" 2
    1
    spec.platforms.openshift.scc.default 指定 OpenShift Pipelines 附加到用于工作负载的服务帐户(SA),默认为 pipeline SA。此 SCC 用于所有管道运行和任务运行 Pod。
    2
    spec.platforms.openshift.scc.maxAllowed 指定您可以为管道运行和任务运行 pod 配置的最低限制 SCC。当您在特定管道运行或任务运行中配置自定义 SA 和 SCC 时,此设置不适用。

2.2. 为命名空间中的 pod 配置 SCC

您可以为 OpenShift Pipelines 为管道运行和您在特定命名空间中运行的所有 Pod 配置安全性上下文约束(SCC)。在 spec.platforms.openshift.scc.maxAllowed spec 中,这个 SCC 不得小于您使用 TektonConfig CR 配置的最大 SCC。

流程

  • 将命名空间的 operator.tekton.dev/scc 注解设置为 SCC 的名称。

    为 OpenShift Pipelines pod 配置 SCC 的命名空间注解示例

    apiVersion: v1
    kind: Namespace
    metadata:
      name: test-namespace
      annotations:
        operator.tekton.dev/scc: nonroot

2.3. 使用自定义 SCC 和自定义服务帐户运行管道运行和任务

当使用与默认 pipelines 服务帐户关联的 pipelines-scc 安全性上下文约束(SCC)时,管道运行和任务运行 Pod 可能会面临超时。这是因为在默认的 pipelines-scc SCC 中,fsGroup.type 参数设置为 MustRunAs

注意

有关 pod 超时的更多信息,请参阅 BZ#1995779.

为避免 pod 超时,您可以创建一个自定义 SCC,并将 fsGroup.type 参数设置为 RunAsAny,并将它与自定义服务帐户关联。

注意

作为最佳实践,使用自定义 SCC 和自定义服务帐户来运行管道运行和任务运行。这种方法具有更大的灵活性,在升级过程中修改默认值时不会中断运行。

流程

  1. 定义自定义 SCC,并将 fsGroup.type 参数设置为 RunAsAny

    示例:自定义 SCC

    apiVersion: security.openshift.io/v1
    kind: SecurityContextConstraints
    metadata:
      annotations:
        kubernetes.io/description: my-scc is a close replica of anyuid scc. pipelines-scc has fsGroup - RunAsAny.
      name: my-scc
    allowHostDirVolumePlugin: false
    allowHostIPC: false
    allowHostNetwork: false
    allowHostPID: false
    allowHostPorts: false
    allowPrivilegeEscalation: true
    allowPrivilegedContainer: false
    allowedCapabilities: null
    defaultAddCapabilities: null
    fsGroup:
      type: RunAsAny
    groups:
    - system:cluster-admins
    priority: 10
    readOnlyRootFilesystem: false
    requiredDropCapabilities:
    - MKNOD
    runAsUser:
      type: RunAsAny
    seLinuxContext:
      type: MustRunAs
    supplementalGroups:
      type: RunAsAny
    volumes:
    - configMap
    - downwardAPI
    - emptyDir
    - persistentVolumeClaim
    - projected
    - secret

  2. 创建自定义 SCC:

    示例:创建 my-scc SCC

    $ oc create -f my-scc.yaml

  3. 创建自定义服务帐户:

    示例:创建一个 fsgroup-runasany 服务帐户

    $ oc create serviceaccount fsgroup-runasany

  4. 将自定义 SCC 与自定义服务帐户关联:

    示例:将 my-scc SCC 与 fsgroup-runasany 服务帐户关联

    $ oc adm policy add-scc-to-user my-scc -z fsgroup-runasany

    如果要将自定义服务帐户用于特权任务,您可以通过运行以下命令将 privileged SCC 与自定义服务帐户关联:

    示例:将 privileged SCC 与 fsgroup-runasany 服务帐户关联

    $ oc adm policy add-scc-to-user privileged -z fsgroup-runasany

  5. 在管道运行和任务运行中使用自定义服务帐户:

    示例:Pipeline 使用 fsgroup-runasany 自定义服务帐户运行 YAML

    apiVersion: tekton.dev/v1
    kind: PipelineRun
    metadata:
      name: <pipeline-run-name>
    spec:
      pipelineRef:
        name: <pipeline-cluster-task-name>
      taskRunTemplate:
        serviceAccountName: 'fsgroup-runasany'

    示例:任务使用 fsgroup-runasany 自定义服务帐户运行 YAML

    apiVersion: tekton.dev/v1
    kind: TaskRun
    metadata:
      name: <task-run-name>
    spec:
      taskRef:
        name: <cluster-task-name>
      taskRunTemplate:
        serviceAccountName: 'fsgroup-runasany'

2.4. 其他资源

第 3 章 使用事件监听程序保护 Webhook

作为管理员,您可以使用事件监听程序保护 Webhook。创建命名空间后,您可以通过将 operator.tekton.dev/enable-annotation=enabled 标签添加到命名空间,为 Eventlistener 资源启用 HTTPS。然后,您可以使用重新加密的 TLS 终止创建 Trigger 资源和安全路由。

Red Hat OpenShift Pipelines 中的触发器支持不安全的 HTTP 和安全 HTTPS 连接到 Eventlistener 资源。HTTPS 保护集群内部和外部的连接。

Red Hat OpenShift Pipelines 运行 tekton-operator-proxy-webhook pod,用于监视命名空间中的标签。当您将标签添加到命名空间时,webhook 在 EventListener 对象上设置 service.beta.openshift.io/serving-cert-secret-name=<secret_name> 注解。这反过来会创建 secret 和所需的证书。

service.beta.openshift.io/serving-cert-secret-name=<secret_name>

另外,您可以将创建的 secret 挂载到 Eventlistener pod 中,以保护请求。

3.1. 提供与 OpenShift 路由的安全连接

要使用重新加密的 TLS 终止创建路由,请运行:

$ oc create route reencrypt --service=<svc-name> --cert=tls.crt --key=tls.key --ca-cert=ca.crt --hostname=<hostname>

或者,您可以创建一个重新加密的 TLS 终止 YAML 文件来创建安全路由。

重新加密 TLS 终止 YAML 示例,以创建安全路由

apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: route-passthrough-secured  1
spec:
  host: <hostname>
  to:
    kind: Service
    name: frontend 2
  tls:
    termination: reencrypt 3
    key: [as in edge termination]
    certificate: [as in edge termination]
    caCertificate: [as in edge termination]
    destinationCACertificate: |- 4
      -----BEGIN CERTIFICATE-----
      [...]
      -----END CERTIFICATE-----

1 2
对象的名称,仅限于 63 个字符。
3
termination 字段设置为 reencrypt。这是唯一需要的 TLS 字段。
4
这是重新加密所必需的。destinationCACertificate 字段指定一个 CA 证书来验证端点证书,从而保护从路由器到目的地 Pod 的连接。您可以在以下情况之一中省略此字段:
  • 服务使用服务签名证书。
  • 管理员为路由器指定默认 CA 证书,服务具有由该 CA 签名的证书。

您可以运行 oc create route reencrypt --help 命令显示更多选项。

3.2. 使用安全 HTTPS 连接创建示例 EventListener 资源

本节使用 pipelines-tutorial 示例来演示使用安全 HTTPS 连接创建示例 EventListener 资源。

流程

  1. 从 pipelines-tutorial 存储库中的 YAML 文件创建 TriggerBinding 资源:

    $ oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/03_triggers/01_binding.yaml
  2. 从 pipelines-tutorial 存储库中的 YAML 文件创建 TriggerTemplate 资源:

    $ oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/03_triggers/02_template.yaml
  3. 直接从 pipelines-tutorial 存储库创建 Trigger 资源:

    $ oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/03_triggers/03_trigger.yaml
  4. 使用安全 HTTPS 连接创建 EventListener 资源:

    1. 添加一个标签,在 Eventlistener 资源中启用安全 HTTPS 连接:

      $ oc label namespace <ns-name> operator.tekton.dev/enable-annotation=enabled
    2. 从 pipelines-tutorial 存储库中的 YAML 文件创建 EventListener 资源:

      $ oc create -f https://raw.githubusercontent.com/openshift/pipelines-tutorial/master/03_triggers/04_event_listener.yaml
    3. 创建带有重新加密 TLS 终止的路由:

      $ oc create route reencrypt --service=<svc-name> --cert=tls.crt --key=tls.key --ca-cert=ca.crt --hostname=<hostname>

第 4 章 使用 secret 使用存储库验证管道

管道和任务可能需要凭证才能使用 Git 存储库和容器存储库进行身份验证。在 Red Hat OpenShift Pipelines 中,您可以使用 secret 验证管道运行和在执行过程中与 Git 存储库交互的任务运行和任务运行。

用于使用 Git 存储库进行身份验证的 secret 称为 Git secret

管道运行或任务运行通过关联的服务帐户获取对 secret 的访问权限。另外,您可以在管道或任务中定义工作区,并将 secret 绑定到工作区。

4.1. 先决条件

  • 已安装 oc OpenShift 命令行工具。

4.2. 使用服务帐户提供 secret

您可以使用服务帐户为 secret 提供 Git 存储库和容器存储库身份验证。

您可以将 secret 与服务帐户关联。机密中的信息可供此服务帐户下运行的任务使用。

4.2.1. 服务帐户的 secret 的类型和注解

如果使用服务帐户提供身份验证 secret,OpenShift Pipelines 支持多种 secret 类型。对于大多数这些 secret 类型,您必须提供注解来定义身份验证 secret 有效的存储库。

4.2.1.1. Git 身份验证 secret

如果使用服务帐户提供身份验证 secret,OpenShift Pipelines 支持以下 Git 身份验证的 secret 类型:

  • kubernetes.io/basic-auth :基本身份验证的用户名和密码
  • kubernetes.io/ssh-auth: 基于 SSH 的身份验证的密钥

如果使用服务帐户提供身份验证 secret,Git secret 必须具有一个或多个注解键。每个键的名称必须以 tekton.dev/git- 开头,值是 OpenShift Pipelines 必须使用 secret 中的凭证的 URL。

在以下示例中,OpenShift Pipelines 使用 basic-auth secret 访问位于 github.comgitlab.com 的存储库。

示例:使用多个 Git 存储库进行基本身份验证的凭证

apiVersion: v1
kind: Secret
metadata:
  name: git-secret-basic
  annotations:
    tekton.dev/git-0: github.com
    tekton.dev/git-1: gitlab.com
type: kubernetes.io/basic-auth
stringData:
  username: <username> 1
  password: <password> 2

1
软件仓库的用户名
2
存储库的密码或个人访问令牌

您还可以使用 ssh-auth secret 为访问 Git 存储库提供私钥,如下例所示:

示例:用于基于 SSH 的身份验证的私钥

apiVersion: v1
kind: Secret
metadata:
  name: git-secret-ssh
  annotations:
    tekton.dev/git-0: https://github.com
type: kubernetes.io/ssh-auth
stringData:
  ssh-privatekey: 1

1
SSH 私钥文件的内容。
4.2.1.2. 容器 registry 身份验证 secret

如果使用服务帐户提供身份验证 secret,OpenShift Pipelines 支持以下容器(Docker) registry 身份验证的 secret 类型:

  • kubernetes.io/basic-auth :基本身份验证的用户名和密码
  • kubernetes.io/dockercfg :序列化的 ~/.dockercfg 文件
  • kubernetes.io/dockerconfigjson :序列化 ~/.docker/config.json 文件

如果使用服务帐户提供身份验证 secret,kubernetes.io/basic-auth 类型的容器 registry secret 必须具有一个或多个注解键。每个键的名称必须以 tekton.dev/docker- 开头,值是 OpenShift Pipelines 必须使用 secret 中的凭证的 URL。其他类型的容器 registry secret 不需要此注解。

在以下示例中,OpenShift Pipelines 使用 basic-auth secret (依赖于用户名和密码)访问位于 quay.iomy-registry.example.com 的容器 registry。

示例:使用多个容器存储库进行基本身份验证的凭证

apiVersion: v1
kind: Secret
metadata:
  name: docker-secret-basic
  annotations:
    tekton.dev/docker-0: quay.io
    tekton.dev/docker-1: my-registry.example.com
type: kubernetes.io/basic-auth
stringData:
  username: <username> 1
  password: <password> 2

1
registry 的用户名
2
registry 的密码或个人访问令牌

您可以从现有配置文件创建 kubernetes.io/dockercfgkubernetes.io/dockerconfigjson secret,如下例所示:

示例:创建用于从现有配置文件中向容器存储库进行身份验证的 secret 的命令

$ oc create secret generic docker-secret-config \
    --from-file=config.json=/home/user/.docker/config.json \
    --type=kubernetes.io/dockerconfigjson

您还可以使用 oc 命令行工具从凭证创建 kubernetes.io/dockerconfigjson secret,如下例所示:

示例:创建用于从凭证向容器存储库进行身份验证的 secret 的命令

$ oc create secret docker-registry docker-secret-config \
  --docker-email=<email> \ 1
  --docker-username=<username> \ 2
  --docker-password=<password> \ 3
  --docker-server=my-registry.example.com:5000 4

1
registry 的电子邮件地址
2
registry 的用户名
3
registry 的密码或个人访问令牌
4
registry 的主机名和端口

4.2.2. 使用服务帐户为 Git 配置基本身份验证

对于管道从密码保护的存储库检索资源,您可以为该管道配置基本身份验证。

注意

考虑使用基于 SSH 的身份验证而不是基本身份验证。

要为管道配置基本身份验证,请创建一个基本身份验证 secret,将此 secret 与服务帐户关联,并将此服务帐户与 TaskRunPipelineRun 资源关联。

注意

对于 GitHub,已弃用使用普通密码进行身份验证。而应使用个人访问令牌

流程

  1. secret.yaml 文件中为 secret 创建 YAML 清单。在此清单中,指定用户名和密码或 GitHub 个人访问令牌来访问 目标 Git 存储库。

    apiVersion: v1
    kind: Secret
    metadata:
      name: basic-user-pass 1
      annotations:
        tekton.dev/git-0: https://github.com
    type: kubernetes.io/basic-auth
    stringData:
      username: <username> 2
      password: <password> 3
    1
    secret 的名称。在本例中,basic-user-pass
    2
    Git 存储库的用户名。
    3
    Git 存储库的密码或个人访问令牌。
  2. serviceaccount.yaml 文件中为服务帐户创建 YAML 清单。在此清单中,将 secret 与服务帐户关联。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: build-bot 1
    secrets:
      - name: basic-user-pass 2
    1
    服务帐户的名称。在本例中,build-bot
    2
    secret 的名称。在本例中,basic-user-pass
  3. run.yaml 文件中的任务运行或管道运行创建 YAML 清单,并将服务帐户与任务运行或管道运行关联。使用以下示例之一:

    • 将服务帐户与 TaskRun 资源关联:

      apiVersion: tekton.dev/v1
      kind: TaskRun
      metadata:
        name: build-push-task-run-2 1
      spec:
        taskRunTemplate:
          serviceAccountName: build-bot 2
        taskRef:
          name: build-push 3
      1
      任务运行的名称。在本例中,build-push-task-run-2
      2
      服务帐户的名称。在本例中,build-bot
      3
      任务的名称。在本例中,build-push
    • 将服务帐户与 PipelineRun 资源关联:

      apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        name: demo-pipeline 1
        namespace: default
      spec:
        taskRunTemplate:
          serviceAccountName: build-bot 2
        pipelineRef:
          name: demo-pipeline 3
      1
      管道运行的名称。在本例中,demo-pipeline
      2
      服务帐户的名称。在本例中,build-bot
      3
      管道的名称。在本例中,demo-pipeline
  4. 输入以下命令应用您创建的 YAML 清单:

    $ oc apply --filename secret.yaml,serviceaccount.yaml,run.yaml

4.2.3. 使用服务帐户为 Git 配置 SSH 身份验证

若要让管道从配置了 SSH 密钥的存储库检索资源,您必须为该管道配置基于 SSH 的身份验证。

要为管道配置基于 SSH 的身份验证,请使用 SSH 私钥创建身份验证 secret,将此 secret 与服务帐户关联,并将此服务帐户与 TaskRunPipelineRun 资源关联。

流程

  1. 生成 SSH 私钥,或复制通常在 ~/.ssh/id_rsa 文件中提供的现有私钥。
  2. secret.yaml 文件中为 secret 创建 YAML 清单。在此清单中,将 ssh-privatekey 的值设置为 SSH 私钥文件的内容,并将 known_hosts 的值设置为已知主机文件的内容。

    apiVersion: v1
    kind: Secret
    metadata:
      name: ssh-key 1
      annotations:
        tekton.dev/git-0: github.com
    type: kubernetes.io/ssh-auth
    stringData:
      ssh-privatekey: 2
      known_hosts: 3
    1
    包含 SSH 私钥的机密的名称。在本例中,ssh-key
    2
    SSH 私钥文件的内容。
    3
    已知主机文件的内容。
    重要

    如果省略已知主机文件,OpenShift Pipelines 会接受任何服务器的公钥。

  3. 可选:通过在注解值末尾添加 :&lt ;port_number& gt; 来指定自定义 SSH 端口。例如: tekton.dev/git-0: github.com:2222
  4. serviceaccount.yaml 文件中为服务帐户创建 YAML 清单。在此清单中,将 secret 与服务帐户关联。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: build-bot 1
    secrets:
      - name: ssh-key 2
    1
    服务帐户的名称。在本例中,build-bot
    2
    包含 SSH 私钥的机密的名称。在本例中,ssh-key
  5. run.yaml 文件中,将服务帐户与任务运行或管道运行关联。使用以下示例之一:

    • 将服务帐户与任务运行关联:

      apiVersion: tekton.dev/v1
      kind: TaskRun
      metadata:
        name: build-push-task-run-2 1
      spec:
        taskRunTemplate:
          serviceAccountName: build-bot 2
        taskRef:
          name: build-push 3
      1
      任务运行的名称。在本例中,build-push-task-run-2
      2
      服务帐户的名称。在本例中,build-bot
      3
      任务的名称。在本例中,build-push
    • 将服务帐户与管道运行关联:

      apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        name: demo-pipeline 1
        namespace: default
      spec:
        taskRunTemplate:
          serviceAccountName: build-bot 2
        pipelineRef:
          name: demo-pipeline 3
      1
      管道运行的名称。在本例中,demo-pipeline
      2
      服务帐户的名称。在本例中,build-bot
      3
      管道的名称。在本例中,demo-pipeline
  6. 应用更改。

    $ oc apply --filename secret.yaml,serviceaccount.yaml,run.yaml

4.2.4. 使用服务帐户配置容器 registry 身份验证

要使管道从 registry 检索容器镜像或将容器镜像推送到 registry,您必须为该 registry 配置身份验证。

要为管道配置 registry 身份验证,请使用 Docker 配置文件创建身份验证 secret,将此 secret 与服务帐户关联,并将此服务帐户与 TaskRunPipelineRun 资源关联。

流程

  1. 输入以下命令,从现有 config.json 文件创建容器 registry 身份验证 secret,该文件包含身份验证信息:

    $ oc create secret generic my-registry-credentials \ 1
      --from-file=config.json=/home/user/credentials/config.json 2
    1
    secret 的名称,本例中为 my-registry-credentials
    2
    config.json 文件的路径名,本例中为 /home/user/credentials/config.json
  2. serviceaccount.yaml 文件中为服务帐户创建 YAML 清单。在此清单中,将 secret 与服务帐户关联。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: container-bot 1
    secrets:
      - name: my-registry-credentials 2
    1
    服务帐户的名称。在本例中,container-bot
    2
    包含 SSH 私钥的机密的名称。在本例中,my-registry-credentials
  3. 为任务运行或管道运行创建 YAML 清单,作为 run.yaml 文件运行。在这个文件中,将服务帐户与任务运行或管道运行关联。使用以下示例之一:

    • 将服务帐户与任务运行关联:

      apiVersion: tekton.dev/v1
      kind: TaskRun
      metadata:
        name: build-container-task-run-2 1
      spec:
        taskRunTemplate:
          serviceAccountName: container-bot 2
        taskRef:
          name: build-container 3
      1
      任务运行的名称。在本例中,build-container-task-run-2
      2
      服务帐户的名称。在本例中,container-bot
      3
      任务的名称。在本例中,build-container
    • 将服务帐户与管道运行关联:

      apiVersion: tekton.dev/v1
      kind: PipelineRun
      metadata:
        name: demo-pipeline 1
        namespace: default
      spec:
        taskRunTemplate:
          serviceAccountName: container-bot 2
        pipelineRef:
          name: demo-pipeline 3
      1
      管道运行的名称。在本例中,demo-pipeline
      2
      服务帐户的名称。在本例中,container-bot
      3
      管道的名称。在本例中,demo-pipeline
  4. 输入以下命令应用更改:

    $ oc apply --filename serviceaccount.yaml,run.yaml

4.2.5. 使用服务帐户进行身份验证的其他注意事项

在某些情况下,您必须完成额外的步骤来使用使用服务帐户提供的身份验证 secret。

4.2.5.1. 任务中的 SSH Git 身份验证

您可以在任务步骤中直接调用 Git 命令并使用 SSH 身份验证,但您必须完成额外的步骤。

OpenShift Pipelines 在 /tekton/home/.ssh 目录中提供 SSH 文件,并将 $HOME 变量设置为 /tekton/home。但是,Git SSH 身份验证会忽略 $HOME 变量,并将 /etc/passwd 文件中指定的主目录用于用户。因此,使用 Git 命令的步骤必须将 /tekton/home/.ssh 目录符号链接到相关用户的主目录。

例如,如果任务以 root 用户身份运行,则步骤必须在 Git 命令前使用以下命令:

apiVersion: tekton.dev/v1
kind: Task
metadata:
  name: example-git-task
spec:
  steps:
    - name: example-git-step
#     ...
      script:
        ln -s $HOME/.ssh /root/.ssh
#     ...

但是,当使用 git 类型的管道资源或 Tekton 目录中提供的 git-clone 任务时,不需要显式符号链接。

有关在 git 类型任务中使用 SSH 身份验证的示例,请参阅 authenticating-git-commands.yaml

4.2.5.2. 以非 root 用户身份使用 secret

在某些情况下,您可能需要将 secret 用作非 root 用户,例如:

  • 容器用于执行运行的用户和组由平台随机化。
  • 任务中的步骤定义非 root 安全性上下文。
  • 任务指定一个全局非 root 安全上下文,它应用到任务中的所有步骤。

在这种情况下,请考虑以非 root 用户身份运行任务和管道运行的以下方面:

  • Git 的 SSH 身份验证要求用户在 /etc/passwd 目录中配置有效的主目录。指定没有有效主目录的 UID 会导致身份验证失败。
  • SSH 身份验证会忽略 $HOME 环境变量。因此,您必须将 OpenShift Pipelines 定义的 $HOME 目录(/tekton/home)中的 secret 文件符号链接到非 root 用户的有效主目录。

另外,要在非 root 安全上下文中配置 SSH 身份验证,请参阅示例中的 git-clone-and-check 步骤,以验证 git 命令

4.3. 使用工作区提供 secret

您可以使用工作区为 secret 提供 Git 存储库和容器存储库身份验证。

您可以在任务中配置指定工作区,指定挂载工作区的路径。运行任务时,将 secret 提供为带有此名称的工作区。当 OpenShift Pipelines 执行任务时,secret 中的信息可供任务使用。

如果您使用工作区提供身份验证 secret,则不需要 secret 的注解。

4.3.1. 使用工作区为 Git 配置 SSH 身份验证

若要让管道从配置了 SSH 密钥的存储库检索资源,您必须为该管道配置基于 SSH 的身份验证。

要为管道配置基于 SSH 的身份验证,请使用 SSH 私钥创建身份验证 secret,在任务中为此 secret 配置命名工作区,并在运行任务时指定 secret。

流程

  1. 输入以下命令从现有 .ssh 目录中的文件创建 Git SSH 身份验证 secret:

    $ oc create secret generic my-github-ssh-credentials \ 1
      --from-file=id_ed25519=/home/user/.ssh/id_ed25519 \ 2
      --from-file=known_hosts=/home/user/.ssh/known_hosts 3
    1
    secret 的名称,在这个示例中,my-github-ssh-credentials
    2
    私钥文件的名称和完整路径名称,本例中为 /home/user/.ssh/id_ed25519
    3
    已知主机文件的名称和完整路径名称,本例中为 /home/user/.ssh/known_hosts
  2. 在任务定义中,为 Git 身份验证配置命名工作区,如 ssh-directory

    工作区的定义示例

    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: git-clone
    spec:
      workspaces:
        - name: ssh-directory
          description: |
            A .ssh directory with private key, known_hosts, config, etc.

  3. 在任务步骤中,使用 $(workspaces.<workspace_name>.path)环境变量中的路径 访问目录,例如 $(workspaces.ssh-directory.path)
  4. 在运行任务时,通过在 tkn task start 命令中包含 the- workspace 参数来指定命名工作区的 secret:

    $ tkn task start <task_name>
          --workspace name=<workspace_name>,secret=<secret_name> 1
          # ...
    1
    <workspace_name > 替换为您配置的工作区的名称,< secret_name > 替换为您创建的 secret 的名称。

使用 SSH 密钥克隆 Git 存储库进行身份验证的任务示例

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: git-clone
spec:
  workspaces:
    - name: output
      description: The git repo will be cloned onto the volume backing this Workspace.
    - name: ssh-directory
      description: |
        A .ssh directory with private key, known_hosts, config, etc. Copied to
        the user's home before git commands are executed. Used to authenticate
        with the git remote when performing the clone. Binding a Secret to this
        Workspace is strongly recommended over other volume types
  params:
    - name: url
      description: Repository URL to clone from.
      type: string
    - name: revision
      description: Revision to checkout. (branch, tag, sha, ref, etc...)
      type: string
      default: ""
    - name: gitInitImage
      description: The image providing the git-init binary that this Task runs.
      type: string
      default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.37.0"
  results:
    - name: commit
      description: The precise commit SHA that was fetched by this Task.
    - name: url
      description: The precise URL that was fetched by this Task.
  steps:
    - name: clone
      image: "$(params.gitInitImage)"
      script: |
        #!/usr/bin/env sh
        set -eu
        # This is necessary for recent version of git
        git config --global --add safe.directory '*'
        cp -R "$(workspaces.ssh-directory.path)" "${HOME}"/.ssh 1
        chmod 700 "${HOME}"/.ssh
        chmod -R 400 "${HOME}"/.ssh/*
        CHECKOUT_DIR="$(workspaces.output.path)/"
        /ko-app/git-init \
          -url="$(params.url)" \
          -revision="$(params.revision)" \
          -path="${CHECKOUT_DIR}"
        cd "${CHECKOUT_DIR}"
        RESULT_SHA="$(git rev-parse HEAD)"
        EXIT_CODE="$?"
        if [ "${EXIT_CODE}" != 0 ] ; then
          exit "${EXIT_CODE}"
        fi
        printf "%s" "${RESULT_SHA}" > "$(results.commit.path)"
        printf "%s" "$(params.url)" > "$(results.url.path)"

1
脚本会将机密的内容(以文件夹的形式)复制到 ${HOME}/.ssh,这是 ssh 搜索凭据的标准文件夹。

运行任务的命令示例

$ tkn task start git-clone
      --param url=git@github.com:example-github-user/buildkit-tekton
      --workspace name=output,emptyDir=""
      --workspace name=ssh-directory,secret=my-github-ssh-credentials
      --use-param-defaults --showlog

4.3.2. 使用工作区配置容器 registry 身份验证

要使管道从 registry 检索容器镜像,您必须为该 registry 配置身份验证。

要为容器 registry 配置身份验证,请使用 Docker 配置文件创建身份验证 secret,在任务中为此 secret 配置名为 workspace,并在运行任务时指定 secret。

流程

  1. 输入以下命令,从现有 config.json 文件创建容器 registry 身份验证 secret,该文件包含身份验证信息:

    $ oc create secret generic my-registry-credentials \ 1
      --from-file=config.json=/home/user/credentials/config.json 2
    1
    secret 的名称,本例中为 my-registry-credentials
    2
    config.json 文件的路径名,本例中为 /home/user/credentials/config.json
  2. 在任务定义中,为 Git 身份验证配置命名工作区,如 ssh-directory

    工作区的定义示例

    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: skopeo-copy
    spec:
      workspaces:
        - name: dockerconfig
          description: Includes a docker `config.json`
    # ...

  3. 在任务步骤中,使用 $(workspaces.<workspace_name>.path) 环境变量中的路径访问目录,如 $(workspaces.dockerconfig.path)
  4. 要运行任务,请在 tkn task start 命令中包含 the- workspace 参数来指定命名工作区的 secret:

    $ tkn task start <task_name>
          --workspace name=<workspace_name>,secret=<secret_name> 1
          # ...
    1
    <workspace_name > 替换为您配置的工作区的名称,< secret_name > 替换为您创建的 secret 的名称。

使用 Skopeo 从容器存储库复制镜像的示例

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: skopeo-copy
spec:
  workspaces:
    - name: dockerconfig 1
      description: Includes a docker `config.json`
  steps:
    - name: clone
      image: quay.io/skopeo/stable:v1.8.0
      env:
      - name: DOCKER_CONFIG
        value: $(workspaces.dockerconfig.path) 2
      script: |
        #!/usr/bin/env sh
        set -eu
        skopeo copy docker://docker.io/library/ubuntu:latest docker://quay.io/example_repository/ubuntu-copy:latest

1
包含 config.json 文件的工作区名称。
2
DOCKER_CONFIG 环境变量指向 dockerconfig 工作区中的 config.json 文件的位置。Skopeo 使用这个环境变量来获取身份验证信息。

运行任务的命令示例

$ tkn task start skopeo-copy
      --workspace name=dockerconfig,secret=my-registry-credentials
      --use-param-defaults --showlog

4.3.3. 使用工作区将 secret 限制到特定步骤

当您使用工作区提供身份验证 secret 并在任务中定义工作区时,默认情况下工作区可用于任务中的所有步骤。

要将 secret 限制到特定的步骤,请在任务规格和步骤规格中定义工作区。

流程

  • 在任务规格和步骤规格中添加 workspaces: 定义,如下例所示:

    任务定义示例,其中只有一个步骤可以访问凭证工作区

    apiVersion: tekton.dev/v1beta1
    kind: Task
    metadata:
      name: git-clone-build
    spec:
      workspaces: 1
        - name: ssh-directory
          description: |
            A .ssh directory with private key, known_hosts, config, etc.
    # ...
      steps:
        - name: clone
          workspaces: 2
            - name: ssh-directory
    # ...
        - name: build 3
    # ...

    1
    任务规格中的 ssh-directory 工作区的定义。
    2
    步骤规格中 ssh-directory 工作区的定义。此步骤可以使用身份验证信息作为 $(workspaces.ssh-directory.path) 目录。
    3
    由于此步骤不包含 ssh-directory 工作区的定义,因此此步骤不提供身份验证信息。

第 5 章 以非 root 用户身份使用 Buildah 构建容器镜像

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

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

5.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。

5.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/v1
    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
    您可以根据需要更改卷挂载的路径。

5.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/ubi9/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/v1
    kind: TaskRun
    metadata:
      name: buildah-as-user-1000
    spec:
      taskRunTemplate:
        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/v1
    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/v1
    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. 启动任务运行或管道运行。

5.4. 无特权构建的限制

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

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

法律通告

Copyright © 2024 Red Hat, Inc.
The text of and illustrations in this document are licensed by Red Hat under a Creative Commons Attribution–Share Alike 3.0 Unported license ("CC-BY-SA"). An explanation of CC-BY-SA is available at http://creativecommons.org/licenses/by-sa/3.0/. In accordance with CC-BY-SA, if you distribute this document or an adaptation of it, you must provide the URL for the original version.
Red Hat, as the licensor of this document, waives the right to enforce, and agrees not to assert, Section 4d of CC-BY-SA to the fullest extent permitted by applicable law.
Red Hat, Red Hat Enterprise Linux, the Shadowman logo, the Red Hat logo, JBoss, OpenShift, Fedora, the Infinity logo, and RHCE are trademarks of Red Hat, Inc., registered in the United States and other countries.
Linux® is the registered trademark of Linus Torvalds in the United States and other countries.
Java® is a registered trademark of Oracle and/or its affiliates.
XFS® is a trademark of Silicon Graphics International Corp. or its subsidiaries in the United States and/or other countries.
MySQL® is a registered trademark of MySQL AB in the United States, the European Union and other countries.
Node.js® is an official trademark of Joyent. Red Hat is not formally related to or endorsed by the official Joyent Node.js open source or commercial project.
The OpenStack® Word Mark and OpenStack logo are either registered trademarks/service marks or trademarks/service marks of the OpenStack Foundation, in the United States and other countries and are used with the OpenStack Foundation's permission. We are not affiliated with, endorsed or sponsored by the OpenStack Foundation, or the OpenStack community.
All other trademarks are the property of their respective owners.
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.