$ oc edit TektonConfig config
Tekton Chains 是一个 Kubernetes 自定义资源定义 (CRD) 控制器。您可以使用它来管理使用 Red Hat OpenShift Pipelines 创建的任务和管道的供应链安全。
默认情况下,Tekton Chains 会观察 OpenShift Container Platform 集群中的所有任务运行执行。任务运行完成后,Tekton Chains 会对任务运行进行快照。然后,它将快照转换为一种或多种标准有效负载格式,最后签署并存储所有工件。
为了捕获有关任务运行的信息,Tekton Chains 使用 `Result` 对象。当对象不可用时,Tekton Chains 使用 OCI 镜像的 URL 和限定摘要。
您可以使用诸如 `cosign` 和 `skopeo` 等工具生成的加密密钥来签署任务运行、任务运行结果和 OCI 注册表镜像。
您可以使用诸如 `in-toto` 等证明格式。
您可以使用 OCI 仓库作为存储后端安全地存储签名和已签署的工件。
Red Hat OpenShift Pipelines 运算符默认情况下会安装 Tekton Chains。您可以通过修改 `TektonConfig` 自定义资源来配置 Tekton Chains;运算符会自动应用您在此自定义资源中所做的更改。
要编辑自定义资源,请使用以下命令:
$ oc edit TektonConfig config
自定义资源包含一个 `chain:` 数组。您可以向此数组添加任何受支持的配置参数,如下例所示:
apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
name: config
spec:
addon: {}
chain:
artifacts.taskrun.format: tekton
config: {}
集群管理员可以使用各种受支持的参数键和值来配置有关任务运行、OCI 镜像和存储的规范。
键 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
存储任务运行有效负载的格式。 |
`in-toto`, `slsa/v1` |
|
|
任务运行签名的存储后端。您可以将多个后端指定为逗号分隔的列表,例如 `“tekton,oci”`。要禁用存储任务运行工件,请提供空字符串 `“”`。 |
`tekton`, `oci`, `gcs`, `docdb`, `grafeas` |
|
|
用于签署任务运行有效负载的签名后端。 |
`x509`, `kms` |
|
`slsa/v1` 是 `in-toto` 的别名,用于向后兼容。 |
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
存储流水线运行负载的格式。 |
`in-toto`, `slsa/v1` |
|
|
存储流水线运行签名的存储后端。您可以指定多个后端,以逗号分隔的列表形式,例如 |
`tekton`, `oci`, `gcs`, `docdb`, `grafeas` |
|
|
用于签署流水线运行负载的签名后端。 |
|
|
|
当此参数为 |
|
|
|
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
存储 OCI 负载的格式。 |
|
|
|
存储 OCI 签名的存储后端。您可以指定多个后端,以逗号分隔的列表形式,例如 |
`tekton`, `oci`, `gcs`, `docdb`, `grafeas` |
|
|
用于签署 OCI 负载的签名后端。 |
|
|
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
要在 |
支持的方案: |
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
用于存储的 GCS 存储桶 |
||
|
用于存储 OCI 签名和证明的 OCI 仓库。 |
如果您将其中一个工件存储后端配置为 |
|
|
为 in-toto 证明设置的构建器 ID |
|
|
|
in-toto 证明的构建类型。当此参数为 |
|
如果您为任何工件启用了 docdb
存储方法,请配置 docstore 存储选项。有关 go-cloud docstore URI 格式的更多信息,请参见 docstore 包文档。Red Hat OpenShift Pipelines 支持以下 docstore 服务
firestore
dynamodb
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
指向 |
|
|
|
用于 |
||
|
位于名为 |
示例值: |
如果您为任何工件启用了 grafeas
存储方法,请配置 Grafeas 存储选项。有关 Grafeas 笔记和事件的更多信息,请参见 Grafeas 概念。
要创建事件,Red Hat OpenShift Pipelines 必须首先创建用于链接事件的笔记。Red Hat OpenShift Pipelines 创建两种类型的事件:ATTESTATION
事件和 BUILD
事件。
Red Hat OpenShift Pipelines 使用可配置的 noteid
作为笔记名称的前缀。它为 ATTESTATION
笔记附加后缀 -simplesigning
,为 BUILD
笔记附加后缀 -intoto
。如果未配置 noteid
字段,Red Hat OpenShift Pipelines 将使用 tekton-<NAMESPACE>
作为前缀。
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
位于用于存储事件的 Grafeas 服务器的 OpenShift Container Platform 项目。 |
||
|
可选:用于所有已创建笔记名称的前缀。 |
无空格的字符串。 |
|
|
可选:Grafeas |
|
您可以选择启用二进制透明度证明的额外上传。
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
启用或禁用自动二进制透明度上传。 |
|
|
|
如果启用,用于上传二进制透明度证明的 URL。 |
|
如果您将 transparency.enabled 设置为 manual ,则只有具有以下注释的任务运行和流水线运行将上传到透明度日志 |
chains.tekton.dev/transparency-upload: "true"
如果您配置了 x509
签名后端,则可以选择使用 Fulcio 启用无密钥签名。
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
启用或禁用从 Fulcio 自动请求证书。 |
|
|
|
如果启用,用于请求证书的 Fulcio 地址。 |
|
|
|
预期的 OIDC 发行者。 |
|
|
|
从中请求 ID 令牌的提供者。 |
|
Red Hat OpenShift Pipelines 会尝试使用每个提供者 |
|
包含 ID 令牌的文件路径。 |
||
|
TUF 服务器的 URL。必须存在 |
|
如果您配置了 kms
签名后端,请根据需要设置 KMS 配置,包括 OIDC 和 Spire。
参数 | 描述 | 支持的值 | 默认值 |
---|---|---|---|
|
KMS 服务器的 URI ( |
||
|
KMS服务器的身份验证令牌( |
||
|
包含KMS服务器身份验证令牌( |
示例值: |
|
|
OIDC身份验证的路径(例如,Vault的 |
||
|
OIDC身份验证的角色。 |
||
|
KMS令牌的Spire套接字URI(例如, |
||
|
从Spire请求SVID的目标受众。 |
您可以使用密钥提供用于docdb
存储的Mongo服务器URL的值(MONGO_SERVER_URL
)。您必须创建此密钥,将其挂载到Tekton Chains控制器上,并将storage.docdb.mongo-server-url-dir
参数设置为挂载密钥的目录。
您已安装OpenShift CLI(oc
)实用程序。
您已使用openshift-pipelines
命名空间的管理员权限登录到您的OpenShift Container Platform集群。
创建一个名为mongo-url
的密钥,其中包含包含Mongo服务器URL值的MONGO_SERVER_URL
文件,方法是输入以下命令:
$ oc create secret generic mongo-url -n tekton-chains \
--from-file=MONGO_SERVER_URL=<path>/MONGO_SERVER_URL (1)
1 | 包含Mongo服务器URL值的MONGO_SERVER_URL 文件的完整路径和名称。 |
在TektonConfig
自定义资源(CR)的chain
部分中,配置将密钥挂载到Tekton Chains控制器上,并将storage.docdb.mongo-server-url-dir
参数设置为挂载密钥的目录,如下例所示:
mongo-url
密钥的示例配置apiVersion: operator.tekton.dev/v1
kind: TektonConfig
metadata:
name: config
spec:
# ...
chain:
disabled: false
storage.docdb.mongo-server-url-dir: /tmp/mongo-url
options:
deployments:
tekton-chains-controller:
spec:
template:
spec:
containers:
- name: tekton-chains-controller
volumeMounts:
- mountPath: /tmp/mongo-url
name: mongo-url
volumes:
- name: mongo-url
secret:
secretName: mongo-url
# ...
您可以使用密钥提供KMS服务器的身份验证令牌。例如,如果KMS提供程序是Hashicorp Vault,则密钥必须包含VAULT_TOKEN
的值。
您必须创建此密钥,将其挂载到Tekton Chains控制器上,并将signers.kms.auth.token-path
参数设置为身份验证令牌文件的完整路径名。
您已安装OpenShift CLI(oc
)实用程序。
您已使用openshift-pipelines
命名空间的管理员权限登录到您的OpenShift Container Platform集群。
创建一个名为kms-secrets
的密钥,其中包含包含KMS服务器身份验证令牌的KMS_AUTH_TOKEN
文件,方法是输入以下命令:
$ oc create secret generic kms-secrets -n tekton-chains \
--from-file=KMS_AUTH_TOKEN=<path_and_name> (1)
1 | 包含KMS服务器身份验证令牌的文件的完整路径和名称,例如/home/user/KMS_AUTH_TOKEN 。您可以使用其他文件名代替KMS_AUTH_TOKEN 。 |
在TektonConfig
自定义资源(CR)的chain
部分中,配置将密钥挂载到Tekton Chains控制器上,并将signers.kms.auth.token-path
参数设置为身份验证令牌文件的完整路径名,如下例所示:
kms-secrets
密钥的示例配置apiVersion: operator.tekton.dev/v1
kind: TektonConfig
metadata:
name: config
spec:
# ...
chain:
disabled: false
signers.kms.auth.token-path: /etc/kms-secrets/KMS_AUTH_TOKEN
options:
deployments:
tekton-chains-controller:
spec:
template:
spec:
containers:
- name: tekton-chains-controller
volumeMounts:
- mountPath: /etc/kms-secrets
name: kms-secrets
volumes:
- name: kms-secrets
secret:
secretName: kms-secrets
# ...
默认情况下,Tekton Chains控制器监控所有命名空间中的资源。您可以自定义Tekton Chains,使其仅在特定命名空间中运行,这可以提供对其操作的细粒度控制。
您已使用cluster-admin
权限登录到您的OpenShift Container Platform集群。
在TektonConfig
CR的chain
部分中,添加--namespace=
参数以包含控制器应监控的命名空间。
以下示例显示了Tekton Chains控制器配置,使其仅监控dev
和test
命名空间内的资源,并相应地过滤PipelineRun
和TaskRun
对象:
apiVersion: operator.tekton.dev/v1alpha1
kind: TektonConfig
metadata:
name: config
spec:
chain:
disabled: false
options:
deployments:
tekton-chains-controller:
spec:
template:
spec:
containers:
- args:
- --namespace=dev, test (1)
name: tekton-chains-controller
1 | 如果未提供--namespace 参数或将其留空,则控制器默认监控所有命名空间。 |
集群管理员可以生成密钥对,并使用Tekton Chains使用Kubernetes密钥签名工件。为了使Tekton Chains正常工作,openshift-pipelines
命名空间中的signing-secrets
密钥中必须存在用于加密密钥的私钥和密码。
目前,Tekton Chains支持x509
和cosign
签名方案。
仅使用一种受支持的签名方案。 |
要将x509
签名方案与Tekton Chains一起使用,您必须满足以下要求:
将私钥存储在signing-secrets
中,结构为x509.pem
。
将私钥存储为未加密的PKCS #8
PEM文件。
密钥类型为ed25519
或ecdsa
。
要将cosign
签名方案与Tekton Chains一起使用,您必须满足以下要求:
将私钥存储在signing-secrets
中,结构为cosign.key
。
将密码存储在signing-secrets
中,结构为cosign.password
。
将私钥存储为ENCRYPTED COSIGN PRIVATE KEY
类型的加密PEM文件。
要将x509
签名方案用于Tekton Chains密钥,您必须生成x509
密钥对。
您可以通过将TektonConfig
自定义资源(CR)中的generateSigningSecret
字段设置为true
来生成x509
密钥对。Red Hat OpenShift Pipelines Operator会生成一个ecdsa
类型的密钥对:一个x509.pem
私钥和一个x509-pub.pem
公钥。Operator会将密钥存储在openshift-pipelines
命名空间中的signing-secrets
密钥中。
如果您将 |
Red Hat OpenShift Pipelines Operator不提供以下功能以限制潜在的安全问题:
密钥轮换
密钥使用情况审核
对密钥的适当访问控制
您已安装OpenShift CLI(oc
)实用程序。
您已使用openshift-pipelines
命名空间的管理员权限登录到您的OpenShift Container Platform集群。
通过运行以下命令编辑TektonConfig
CR:
$ oc edit TektonConfig config
在TektonConfig
CR中,将generateSigningSecret
值设置为true
。
apiVersion: operator.tekton.dev/v1
kind: TektonConfig
metadata:
name: config
spec:
# ...
chain:
disabled: false
generateSigningSecret: true (1)
# ...
1 | 默认值为false 。将值设置为true 会生成ecdsa 密钥对。 |
您可以使用cosign
工具,将cosign
签名方案与Tekton Chains一起使用。
您已安装cosign工具。
通过运行以下命令生成cosign.key
和cosign.pub
密钥对:
$ cosign generate-key-pair k8s://openshift-pipelines/signing-secrets
Cosign会提示您输入密码,然后创建一个Kubernetes密钥。
将加密的cosign.key
私钥和cosign.password
解密密码存储在signing-secrets
Kubernetes密钥中。确保私钥存储为ENCRYPTED COSIGN PRIVATE KEY
类型的加密PEM文件。
您可以使用skopeo
工具生成密钥,并在 Tekton Chains 的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
工具对密码进行编码,运行以下命令:
$ echo -n '<passphrase>' | base64 -w 0 > b64.passphrase (1)
1 | 将<passphrase> 替换为您为密钥对使用的密码。 |
在openshift-pipelines
命名空间中创建signing-secrets
密钥,运行以下命令:
$ oc create secret generic signing-secrets -n openshift-pipelines
编辑signing-secrets
密钥,运行以下命令:
$ oc edit secret -n openshift-pipelines signing-secrets
以以下方式在密钥的数据中添加编码后的密钥:
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 文件的内容。 |
在将签名推送到 OCI 注册表之前,集群管理员必须配置 Tekton Chains 以对注册表进行身份验证。Tekton Chains 控制器使用任务运行所使用的相同服务帐户。要设置具有将签名推送到 OCI 注册表所需凭据的服务帐户,请执行以下步骤:
设置 Kubernetes 服务帐户的命名空间和名称。
$ export NAMESPACE=<namespace> (1)
$ export SERVICE_ACCOUNT_NAME=<service_account> (2)
1 | 与服务帐户关联的命名空间。 |
2 | 服务帐户的名称。 |
创建一个 Kubernetes 密钥。
$ oc create secret registry-credentials \
--from-file=.dockerconfigjson \ (1)
--type=kubernetes.io/dockerconfigjson \
-n $NAMESPACE
1 | 替换为 Docker 配置文件的路径。默认路径为~/.docker/config.json 。 |
使服务帐户能够访问密钥。
$ oc patch serviceaccount $SERVICE_ACCOUNT_NAME \
-p "{\"imagePullSecrets\": [{\"name\": \"registry-credentials\"}]}" -n $NAMESPACE
如果您修补 Red Hat OpenShift Pipelines 分配给所有任务运行的默认pipeline
服务帐户,则 Red Hat OpenShift Pipelines 运算符将覆盖该服务帐户。最佳实践是,您可以执行以下步骤:
创建一个单独的服务帐户以分配给用户的任务运行。
$ oc create serviceaccount <service_account_name>
通过设置任务运行模板中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 | 替换为新创建的服务帐户的名称。 |
要使用 Tekton Chains 验证任务运行的签名而无需任何额外身份验证,请执行以下任务:
生成加密的x509
或cosign
密钥对,并将其存储为 Kubernetes 密钥。
配置 Tekton Chains 后端存储。
创建任务运行,对其进行签名,并将签名和有效负载存储为任务运行本身上的注释。
从已签名的任务运行中检索签名和有效负载。
验证任务运行的签名。
确保集群上安装了以下组件:
Red Hat OpenShift Pipelines 运算符
Tekton Chains
生成加密的x509
或cosign
密钥对。有关创建密钥对并将其保存为密钥的更多信息,请参见“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 Chains 的更多信息,请参见“配置 Tekton Chains”。
要重新启动 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 替换为公钥文件的路径名。示例输出:
|
集群管理员可以通过执行以下任务来使用 Tekton Chains 签名和验证镜像和来源:
生成加密的x509
或cosign
密钥对,并将其存储为 Kubernetes 密钥。
设置 OCI 注册表的身份验证,以存储镜像、镜像签名和已签名的镜像声明。
配置 Tekton Chains 以生成和签名来源。
在任务运行中使用 Kaniko 创建镜像。
验证已签名的镜像和已签名的来源。
确保集群上安装了以下内容:
生成加密的x509
或cosign
密钥对。有关创建密钥对并将其保存为密钥的更多信息,请参见“Tekton Chains 中用于签名数据的密钥”。
配置镜像注册表的身份验证。
要配置 Tekton Chains 控制器以将签名推送到 OCI 注册表,请使用与任务运行的服务帐户关联的凭据。有关详细信息,请参见“向 OCI 注册表进行身份验证”部分。
要为构建并向注册表推送镜像的 Kaniko 任务配置身份验证,请创建包含所需凭据的 docker config.json
文件的 Kubernetes 密钥。
$ oc create secret generic <docker_config_secret_name> \ (1)
--from-file <path_to_config.json> (2)
1 | 替换为 docker config 密钥的名称。 |
2 | 替换为 docker config.json 文件的路径。 |
通过设置chains-config
对象中的artifacts.taskrun.format
、artifacts.taskrun.storage
和transparency.enabled
参数来配置 Tekton Chains。
$ 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)
1 | 替换为您要推送镜像的注册表的 URL。 |
2 | 替换为 docker config.json 文件中密钥的名称。 |
启动 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 生成来源并对其进行签名,然后检查任务运行上chains.tekton.dev/signed=true
注释的可用性。
$ oc get tr <task_run_name> \ (1)
-o json | jq -r .metadata.annotations
{
"chains.tekton.dev/signed": "true",
...
}
1 | 替换为任务运行的名称。 |
验证镜像和声明。
$ 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)
...
1 | 替换为镜像的 sha256 摘要。 |
2 | 第一个匹配的通用唯一标识符 (UUID)。 |
3 | 第二个匹配的 UUID。 |
搜索结果显示匹配条目的 UUID。其中一个 UUID 包含证明。
检查证明。
$ rekor-cli get --uuid <uuid> --format json | jq -r .Attestation | base64 --decode | jq