4.16. 为 OpenShift Pipelines 提供链安全使用 Tekton 链
Tekton 链只是一个技术预览功能。技术预览功能不受红帽产品服务等级协议(SLA)支持,且功能可能并不完整。红帽不推荐在生产环境中使用它们。这些技术预览功能可以使用户提早试用新的功能,并有机会在开发阶段提供反馈意见。
有关红帽技术预览功能支持范围的更多信息,请参阅技术预览功能支持范围。
Tekton Chains 是一个 Kubernetes 自定义资源定义(CRD)控制器。您可以使用它来管理使用 Red Hat OpenShift Pipelines 创建的任务和管道的供应链安全。
默认情况下,Tekton Chains 会观察 OpenShift Container Platform 集群中的所有任务运行执行。当任务运行完成时,Tekton Chains 会获取任务运行的快照。然后,它会将快照转换为一个或多个标准有效负载格式,最后签署并存储所有工件。
要捕获有关任务运行的信息,Tekton Chains 使用 Result
和 PipelineResource
对象。当对象不可用时,Tekton 会链 OCI 镜像的 URL 和合格摘要。
PipelineResource
对象已弃用,并将在以后的发行版本中删除 ; 对于手动使用,建议使用 Results
对象。
4.16.1. 主要特性
-
您可以使用加密密钥类型和服务(如
cosign
)为任务运行、任务运行结果和 OCI registry 镜像签名。 -
您可以使用"测试"格式,如
in-toto
。 - 您可以使用 OCI 存储库作为存储后端安全存储签名和签名工件。
4.16.2. 使用 Red Hat OpenShift Pipelines Operator 安装 Tekton 链
集群管理员可以使用 TektonChain
自定义资源(CR)来安装和管理 Tekton 链。
Tekton Chains 是 Red Hat OpenShift Pipelines 的一个可选组件。目前,您无法使用 TektonConfig
CR 安装它。
先决条件
-
确保在集群中的
openshift-pipelines
命名空间中安装了 Red Hat OpenShift Pipelines Operator。
流程
为 OpenShift Container Platform 集群创建
TektonChain
CR。apiVersion: operator.tekton.dev/v1alpha1 kind: TektonChain metadata: name: chain spec: targetNamespace: openshift-pipelines
应用
TektonChain
CR。$ oc apply -f TektonChain.yaml 1
- 1
- 使用
TektonChain
CR 的文件名替换。
检查安装的状态。
$ oc get tektonchains.operator.tekton.dev
4.16.3. 配置 Tekton 链
Tekton Chains 在 openshift-pipelines
命名空间中使用名为 chains-config
的 ConfigMap
对象进行配置。
要配置 Tekton 链,请使用以下示例:
示例:配置 Tekton 链
$ oc patch configmap chains-config -n openshift-pipelines -p='{"data":{"artifacts.oci.storage": "", "artifacts.taskrun.format":"tekton", "artifacts.taskrun.storage": "tekton"}}' 1
- 1
- 在 JSON 有效负载中使用支持的键值对组合。
4.16.3.1. Tekton Chains 配置支持的键
集群管理员可以使用各种支持的键和值来配置任务运行、OCI 镜像和存储的规格。
4.16.3.1.1. 任务运行支持的键
支持的键 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
| 存储任务运行有效负载的格式。 |
|
|
|
任务运行签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 |
|
|
| 签名后端为任务运行有效负载进行签名。 |
|
|
4.16.3.1.2. OCI 支持的密钥
支持的键 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
| 存储 OCI 有效负载的格式。 |
|
|
|
OCI 签名的存储后端。您可以将多个后端指定为用逗号分开的列表,如 |
|
|
| 签名后端以签署 OCI 有效负载。 |
|
|
4.16.3.1.3. 支持的存储密钥
支持的键 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
| 用于存储 OCI 签名的 OCI 存储库。 | 目前,链仅支持内部 OpenShift OCI registry;不支持 Quay 等其他流行选项。 |
4.16.4. 在 Tekton Chains 中签名 secret
集群管理员可以生成密钥对,并使用 Tekton 链来使用 Kubernetes secret 为工件签名。要使 Tekton 链正常工作,加密的密钥和密码必须作为 openshift-pipelines
命名空间中的 signing-secrets
Kubernetes secret 的一部分存在。
目前,Tekton 链支持 x509
和 cosign
签名方案。
只使用一个受支持的签名方案。
4.16.4.1. 使用 x509 进行签名
要将 x509
签名方案与 Tekton Chains 搭配使用,请将 ed25519
或 ecdsa
类型的 x509.pem
私钥存储在 signing-secrets
Kubernetes secret 中。确保密钥保存为未加密的 PKCS8 PEM 文件(BEGIN PRIVATE KEY
)。
4.16.4.2. 使用 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-secrets
Kubernetes secret 中。确保私钥存储为ENCRYPTED COSIGN PRIVATE KEY
类型的加密 PEM 文件。
4.16.4.3. 签名故障排除
如果签名 secret 已填充,您可能会遇到以下错误:
Error from server (AlreadyExists): secrets "signing-secrets" already exists
要解决这个问题:
删除 secret:
$ oc delete secret signing-secrets -n openshift-pipelines
- 重新创建密钥对并使用您首选的签名方案将其存储在 secret 中。
4.16.5. 对 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
- 使用新创建的服务帐户的名称替换。
4.16.5.1. 创建和验证任务运行签名而无需任何其他身份验证
要验证使用 Tekton 链与任何其他身份验证一起运行的任务的签名,请执行以下任务:
- 创建加密的 x509 密钥对,并将它保存为 Kubernetes secret。
- 配置 Tekton Chains 后端存储。
- 创建任务运行,为它签名并将签名和有效负载存储为任务运行自身时的注解。
- 从已签名任务运行中检索签名和有效负载。
- 验证任务运行的签名。
先决条件
确保在集群中安装了以下内容:
- Red Hat OpenShift Pipelines Operator
- Tekton Chains
- Cosign
流程
创建加密的 x509 密钥对,并将它保存为 Kubernetes secret:
$ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets
提示时提供密码。Cosign 将生成的私钥存储为
openshift-pipelines
命名空间中的signing-secrets
Kubernetes secret 的一部分。在 Tekton Chains 配置中,禁用 OCI 存储,并将任务运行存储和格式设置为
tekton
。$ oc patch configmap chains-config -n openshift-pipelines -p='{"data":{"artifacts.oci.storage": "", "artifacts.taskrun.format":"tekton", "artifacts.taskrun.storage": "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 taskrun.tekton.dev/build-push-run-output-image-qbjvh created
- 1
- 使用指向您的任务运行的 URI 或文件路径替换。
检查步骤的状态,并等待 till 进程完成。
$ 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
编码注解的对象检索签名和有效负载:$ export TASKRUN_UID=$(tkn tr describe --last -o jsonpath='{.metadata.uid}') $ tkn tr describe --last -o jsonpath="{.metadata.annotations.chains\.tekton\.dev/signature-taskrun-$TASKRUN_UID}" > signature $ tkn tr describe --last -o jsonpath="{.metadata.annotations.chains\.tekton\.dev/payload-taskrun-$TASKRUN_UID}" | base64 -d > payload
验证签名。
$ cosign verify-blob --key k8s://openshift-pipelines/signing-secrets --signature ./signature ./payload Verified OK
4.16.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-secrets
Kubernetes 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