3.17. 为 OpenShift Pipelines 提供链安全使用 Tekton 链
Tekton Chains 是一个 Kubernetes 自定义资源定义(CRD)控制器。您可以使用它来管理使用 Red Hat OpenShift Pipelines 创建的任务和管道的供应链安全。
默认情况下,Tekton Chains 会观察 OpenShift Container Platform 集群中的所有任务运行执行。当任务运行完成时,Tekton Chains 会获取任务运行的快照。然后,它会将快照转换为一个或多个标准有效负载格式,最后签署并存储所有工件。
要捕获有关任务运行的信息,Tekton Chains 使用 Result 对象。当对象不可用时,Tekton 会链 OCI 镜像的 URL 和合格摘要。
3.17.1. 主要特性
-
您可以使用如
cosign和skopeo等加密密钥为任务运行、任务运行结果和 OCI registry 镜像签名。 -
您可以使用"测试"格式,如
in-toto。 - 您可以使用 OCI 存储库作为存储后端安全存储签名和签名工件。
3.17.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: {}3.17.2.1. Tekton Chains 配置支持的参数
集群管理员可以使用各种支持的参数键和值来配置任务运行、OCI 镜像和存储的规格。
3.17.2.1.1. 任务运行工件支持的参数
表 3.19. 链配置:任务运行工件支持的参数
| 键 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 存储任务运行有效负载的格式。 |
|
|
|
|
任务运行签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 |
|
|
|
| 用于签名任务运行有效负载的签名后端。 |
|
|
slsa/v1 是 in-toto 的别名,用于向后兼容。
3.17.2.1.2. 管道运行工件支持的参数
表 3.20. 链配置:管道运行工件支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 存储管道运行有效负载的格式。 |
|
|
|
|
用于存储管道运行签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 |
|
|
|
| 用于签名管道运行有效负载的签名后端。 |
|
|
-
slsa/v1是in-toto的别名,用于向后兼容。 -
对于
grafeas存储后端,只支持 Container Analysis。您无法在 Tekton 链的当前版本中配置grafeas服务器地址。
3.17.2.1.3. OCI 工件支持的参数
表 3.21. 链配置: OCI 工件支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 存储 OCI 有效负载的格式。 |
|
|
|
|
用于存储 OCI 签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 |
|
|
|
| 用于签名 OCI 有效负载的签名后端。 |
|
|
3.17.2.1.4. KMS 符号支持的参数
表 3.22. 链配置: KMS 符号支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
|
对要在 |
支持的方案: |
3.17.2.1.5. 支持的存储参数
表 3.23. 链配置:存储支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 存储的 GCS 存储桶 | ||
|
| 用于存储 OCI 签名和测试的 OCI 存储库。 |
如果您将其中一个工件存储后端配置为 | |
|
| 为 in-toto attestations 设置的构建器 ID |
|
如果您启用了 docdb 存储方法用于任何工件,请配置 docstore 存储选项。有关 go-cloud docstore URI 格式的更多信息,请参阅文档 存储软件包文档。Red Hat OpenShift Pipelines 支持以下 docstore 服务:
-
firestore -
dynamodb
表 3.24. 链配置:docstore 存储支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
|
对 |
|
如果您为任何工件启用 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> 作为前缀。
表 3.25. 链配置:Grafeas 存储支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| Grafeas 服务器用于存储发生的 OpenShift Container Platform 项目。 | ||
|
| 可选:用于所有创建备注的名称的前缀。 | 没有空格的字符串。 | |
|
|
可选:Grafeas |
|
另外,您还可以在测试时启用额外的二进制透明度上传。
表 3.26. 链配置:支持参数,以获得透明测试存储
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 启用或禁用自动二进制透明度上传。 |
|
|
|
| 如果启用,用于上传二进制透明度的 URL。 |
|
如果将 transparency.enabled 设置为 manual,则只有带有以下注解的任务和管道运行上传到透明度日志中:
chains.tekton.dev/transparency-upload: "true"
如果配置 x509 签名后端,您可以选择使用 Fulcio 启用无密钥签名。
表 3.27. 链配置:使用 Fulcio 进行 x509 密钥无密钥签名的支持参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
| 从 Fulcio 启用或禁用请求自动证书。 |
|
|
|
| 请求证书的 Fulcio 地址(如果启用)。 |
| |
|
| 预期的 OIDC 签发者。 |
| |
|
| 从中请求 ID 令牌的供应商。 |
| Red Hat OpenShift Pipelines 会尝试使用每个供应商 |
|
| 包含 ID 令牌的文件的路径。 | ||
|
|
TUF 服务器的 URL。必须存在 |
|
如果您配置 kms 签名后端,请根据需要设置 KMS 配置,包括 OIDC 和 Spire。
表 3.28. 链配置: KMS 签名支持的参数
| 参数 | 描述 | 支持的值 | 默认值 |
|---|---|---|---|
|
|
KMS 服务器的 URI ( |
|
KMS 服务器的身份验证令牌 ( |
|
|
OIDC 身份验证的路径(例如,Vault 为 |
| OIDC 身份验证的角色。 |
|
|
KMS 令牌的 Spire 套接字的 URI (例如: |
| 从 Spire 请求 SVID 的受众。 |
3.17.3. 在 Tekton Chains 中签名数据的 secret
集群管理员可以生成密钥对,并使用 Tekton 链来使用 Kubernetes secret 为工件签名。要使 Tekton 链正常工作,加密的密钥和密码必须存在,作为 openshift-pipelines 命名空间中的 signing-secrets secret 的一部分。
目前,Tekton 链支持 x509 和 cosign 签名方案。
只使用一个受支持的签名方案。
要将 x509 签名方案与 Tekton Chains 搭配使用,请将 ed25519 或 ecdsa 类型的 x509.pem 私钥存储在 signing-secrets Kubernetes secret 中。
3.17.3.1. 使用 cosign 进行签名
您可以使用 cosign 工具使用带有 Tekton 链的 cosign 签名方案。
先决条件
- 已安装 cosign 工具。
流程
运行以下命令,生成
cosign.key和cosign.pub密钥对:$ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets
Cosign 会提示您输入密码,然后创建一个 Kubernetes secret。
-
将加密的
cosign.key私钥和cosign.password解密密码存储在signing-secretsKubernetes secret 中。确保私钥存储为ENCRYPTED COSIGN PRIVATE KEY类型的加密 PEM 文件。
3.17.3.2. 使用 skopeo 进行签名
您可以使用 skopeo 工具生成密钥,并在带有 Tekton 链的 cosign 签名方案中使用它们。
先决条件
- 已安装 skopeo 工具。
流程
运行以下命令生成公钥/私钥对:
$ skopeo generate-sigstore-key --output-prefix <mykey> 1- 1
- 将
<mykey>替换为您选择的密钥名称。
Skopeo 会提示您输入私钥的密码短语,然后创建名为
<mykey>.private和<mykey>.pub的密钥文件。运行以下命令,使用
base64工具对<mykey>.pub文件进行编码:$ base64 -w 0 <mykey>.pub > b64.pub
运行以下命令,使用
base64工具对<mykey>.private文件进行编码:$ base64 -w 0 <mykey>.private > b64.private
运行以下命令,使用
base64工具对 passhprase 进行编码:$ echo -n '<passphrase>' | base64 -w 0 > b64.passphrase 1- 1
- 将
<passphrase>替换为用于密钥对的密码短语。
运行以下命令,在
openshift-pipelines命名空间中创建signing-secretssecret:$ oc create secret generic signing-secrets -n openshift-pipelines
运行以下命令来编辑
signing-secretssecret:$ 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
3.17.3.3. 解决 "secret already exists" 错误
如果 signing-secret secret 已经填充,则创建此 secret 的命令可能会输出以下出错信息:
Error from server (AlreadyExists): secrets "signing-secrets" already exists
您可以通过删除 secret 来解决这个问题。
流程
运行以下命令来删除
signing-secretsecret:$ oc delete secret signing-secrets -n openshift-pipelines
- 重新创建密钥对,并使用您首选的签名方案将其存储在机密中。
3.17.4. 对 OCI registry 进行身份验证
在将签名推送到 OCI Registry 之前,集群管理员必须配置 Tekton 链,以便与 registry 进行身份验证。Tekton Chains 控制器使用与任务运行相同的服务帐户。要设置具有所需凭证(push)到 OCI registry 的服务帐户,请执行以下步骤:
流程
设置 Kubernetes 服务帐户的命名空间和名称。
$ export NAMESPACE=<namespace> 1 $ export SERVICE_ACCOUNT_NAME=<service_account> 2
创建 Kubernetes secret。
$ oc create secret registry-credentials \ --from-file=.dockerconfigjson \ 1 --type=kubernetes.io/dockerconfigjson \ -n $NAMESPACE- 1
- 使用 Docker 配置文件的路径替换。默认路径为
~/.docker/config.json。
授予服务帐户对 secret 的访问权限。
$ oc patch serviceaccount $SERVICE_ACCOUNT_NAME \ -p "{\"imagePullSecrets\": [{\"name\": \"registry-credentials\"}]}" -n $NAMESPACE如果对 Red Hat OpenShift Pipelines 分配到所有任务的默认
pipeline服务帐户进行补丁,Red Hat OpenShift Pipelines Operator 将覆盖服务帐户。作为最佳实践,您可以执行以下步骤:创建单独的服务帐户,以分配给用户的任务运行。
$ oc create serviceaccount <service_account_name>
通过设置任务运行模板中的
serviceaccountname字段的值,将服务帐户关联到运行任务。apiVersion: tekton.dev/v1beta1 kind: TaskRun metadata: name: build-push-task-run-2 spec: serviceAccountName: build-bot 1 taskRef: name: build-push ...- 1
- 使用新创建的服务帐户的名称替换。
3.17.5. 创建和验证任务运行签名而无需任何其他身份验证
要验证使用 Tekton 链与任何其他身份验证一起运行的任务的签名,请执行以下任务:
- 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。
- 配置 Tekton Chains 后端存储。
- 创建任务运行,为它签名并将签名和有效负载存储为任务运行自身时的注解。
- 从已签名任务运行中检索签名和有效负载。
- 验证任务运行的签名。
先决条件
确保在集群中安装了以下组件:
- Red Hat OpenShift Pipelines Operator
- Tekton Chains
- Cosign
流程
- 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。有关创建密钥对并将其保存为 secret 的更多信息,请参阅 "Signing secrets in Tekton Chains"。
在 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 链"。要重启 Tekton Chains 控制器以确保应用了修改后的配置,请输入以下命令:
$ oc delete po -n openshift-pipelines -l app=tekton-chains-controller
输入以下命令来创建任务运行:
$ 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
输入以下命令来检查步骤的状态。等待进程完成。
$ 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
要从存储为
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}')- 要使用您创建的公钥验证签名,请输入以下命令:
$ 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
3.17.5.1. 其他资源
3.17.6. 使用 Tekton 链来签名和验证镜像并证明
集群管理员可以通过执行以下任务来使用 Tekton 链来签名和验证镜像和验证镜像:
- 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。
- 为 OCI registry 设置身份验证,以在测试过程中存储镜像、镜像签名和签名的镜像。
- 配置 Tekton 链以生成和签署认可。
- 在任务运行中,使用 Kaniko 创建镜像。
- 验证已签名的镜像及已签名证明。
先决条件
确保在集群中安装了以下内容:
流程
创建加密的 x509 密钥对,并将它保存为 Kubernetes secret:
$ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets
提示时提供密码。Cosign 将生成的私钥作为 openshift-pipelines 命名空间中的
signing-secretsKubernetes secret 的一部分存储在openshift-pipelines命名空间中,并将公钥写入cosign.pub本地文件。为镜像 registry 配置身份验证。
- 要将 Tekton Chains 控制器配置为将签名推送到 OCI registry,请使用与任务运行服务帐户关联的凭证。如需更多信息,请参阅"授权到 OCI registry"部分。
要为构建并推送到 registry 的 Kaniko 任务配置身份验证,请创建一个包含所需凭证的 docker
config.json文件的 Kubernetes secret。$ oc create secret generic <docker_config_secret_name> \ 1 --from-file <path_to_config.json> 2
通过在
chains-config对象中设置artifacts.taskrun.format、artifacts.taskrun.storage和transparency.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"}}'启动 Kaniko 任务。
将 Kaniko 任务应用到集群。
$ oc apply -f examples/kaniko/kaniko.yaml 1- 1
- 使用 Kaniko 任务的 URI 或文件路径替换。
设置适当的环境变量。
$ export REGISTRY=<url_of_registry> 1 $ export DOCKERCONFIG_SECRET_NAME=<name_of_the_secret_in_docker_config_json> 2
启动 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。
等待一分钟,以允许 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
- 使用任务运行的名称替换。
验证镜像和 attestation。
$ cosign verify --key cosign.pub $REGISTRY/kaniko-chains $ cosign verify-attestation --key cosign.pub $REGISTRY/kaniko-chains
在 Rekor 中找到镜像的验证情况。
- 获取 $REGISTRY/kaniko-chains 镜像摘要。您可以搜索任务运行或拉取镜像以提取摘要。
搜索 Rekor 以查找与镜像
sha256摘要匹配的所有条目。$ rekor-cli search --sha <image_digest> 1 <uuid_1> 2 <uuid_2> 3 ...
搜索结果显示匹配条目的 UUID。其中其中一个 UUID 包含 attestation。
检查 attestation。
$ rekor-cli get --uuid <uuid> --format json | jq -r .Attestation | base64 --decode | jq