验证映像和非映像工件特征符
通过验证映像签名,在部署之前维护在 Continuous Integration (CI) 管道中构建的映像的完整性。
准备工作
在开始使用图像验证功能之前,请确保您已满足以下先决条件。
验证映像
新的 prod-verify-artifact 阶段将验证 Continuous Delivery (CD) 管道中映像的特征符。 此阶段执行以下步骤:
-
将用户提供的编码 GPG 公用密钥解码为临时文件。
-
使用公用密钥创建 Docker 容器策略 (
/etc/containers/policy.json)。{ "default": [ { "type": "reject" } ], "transports": { "docker-daemon": { "": [ { "type": "reject" } ] }, "docker": { "": [ { "type": "signedBy", "keyType": "GPGKeys", "keyPath": "/tmp/GPGPublicKey" } ] } } } -
通过使用 Skopeo 通过容器策略来拉取映像,检索每个工件的工件列表。
skopeo copy docker://"${image}" dir:"${tmp_sign_dir}" --src-creds iamapikey:"${ibmcloud_api_key}"
如果签名有效并由用户提供的公用密钥进行验证,那么映像拉取成功。
配置注册表凭据以供验证
在验证容器镜像签名时,管道需要凭据来对容器注册表进行身份验证,并访问已签名的镜像。 DevSecOps 管道支持运行时动态凭据解析,允许您通过多种方式配置凭据,并具备自动回退机制。
凭证解析层次结构
该管道在运行时会根据以下优先级顺序动态解析用户名和 API 密钥凭据:
API 密钥解析顺序:
- 特定于命名空间的 API 密钥:
signing-token-apikey-{registry}-{namespace}(密钥) - 注册表专用 API 密钥:
signing-token-apikey-{registry}(密钥) - Docker 配置 JSON:
signing-dockerconfigjson(密钥) - ICR 特定的备用方案:
ciso-ibmcloud-api-key(秘密)ibmcloud-api-key(秘密)
用户名解析顺序:
- 命名空间专用用户名:
signing-token-username-{registry}-{namespace}(环境变量) - 注册表专用用户名:
signing-token-username-{registry}(环境变量) - 默认值:
iamapikey(如果未配置用户名)
其中:
{registry}是注册表的主机名(例如:us.icr.io、de.icr.io){namespace}这是完整的命名空间路径,其中斜杠和点已被下划线替换(例如:my_namespace_path)
配置命名空间专用凭据
为了实现精细的访问控制,您可以配置针对特定注册表命名空间的凭据:
API密钥(密钥):signing-token-apikey-{registry}-{namespace}
用户名(环境变量):signing-token-username-{registry}-{namespace}
示例:关于图片 us.icr.io/my-namespace/my-app:latest
- registry:
us.icr.io - 命名空间:
my-namespace - API密钥密钥:
signing-token-apikey-us.icr.io-my_namespace - 用户名环境变量:
signing-token-username-us.icr.io-my_namespace - 如果未提供用户名,则默认为:
iamapikey
配置注册表专用凭据
若要在注册表的所有命名空间中实现更广泛的访问:
API密钥(密钥):signing-token-apikey-{registry}
用户名(环境变量):signing-token-username-{registry}
示例:对于任何位于 us.icr.io
- API密钥密钥:
signing-token-apikey-us.icr.io - 用户名环境变量:
signing-token-username-us.icr.io - 如果未提供用户名,则默认为:
iamapikey
配置 Docker 的JSON配置文件
您可以提供一个包含多个注册表凭据的 base64-encoded Docker 配置 JSON 文件:
秘密名称:signing-dockerconfigjson
格式:Base64-encoded 符合 Docker 网站上 config.json 格式的 JSON:
{
"auths": {
"us.icr.io": {
"username": "iamapikey",
"password": "your-api-key"
},
"us.icr.io/my-namespace": {
"username": "iamapikey",
"password": "namespace-specific-key"
}
}
}
该管道会优先匹配最具体的路径,从而允许在 Docker 配置中进行命名空间级别的覆盖。
示例配置
关于图片 us.icr.io/production/my-app:v1.0.0:
选项 1:命名空间专用(建议用于生产环境)
- API密钥密钥:
signing-token-apikey-us.icr.io-production=your-namespace-api-key - 用户名环境变量(可选):
signing-token-username-us.icr.io-production=iamapikey - 如果未指定用户名,则默认为
iamapikey
选项 2:全局注册表
- API密钥密钥:
signing-token-apikey-us.icr.io=your-registry-api-key - 用户名环境变量(可选):
signing-token-username-us.icr.io=iamapikey - 如果未指定用户名,则默认为
iamapikey
选项 3:Docker 配置 JSON
- 秘诀:
signing-dockerconfigjson=base64-encoded-docker-config - 用户名是从 Docker 的配置 JSON 中提取的
选项 4:IBM Cloud (默认值,ICR 模式下自动处理)
- API密钥密钥:
ibmcloud-api-key=your-ibmcloud-api-key - 用户名默认为
iamapikey
验证非图像工件
在 DevSecOps 管道中,签名构建产物的签名需经过验证。 本节概述了用户在继续工件验证之前必须满足的先决条件。
准备工作
在可以使用图像验证之前,请确保您具有以下先决条件。
-
修改管道配置以启用验证过程。 将以下代码片段添加到你的
.pipeline-config.yaml文件中。verify-artifact: image: icr.io/continuous-delivery/pipeline/image-signing:1.0.0@sha256:e9d8e354668ba3d40be2aaee08298d2aa7f0e1c8a1829cca4094ec93830e3e6a image_pull_policy: IfNotPresent abort_on_failure: false dind: true script: | #!/usr/bin/env bash source /opt/commons/verify-artifact/verify_non_image_artifact.sh -
下载工件并将其存储在管道运行时中。
在调用
verify-artifact阶段之前,请下载所需工件并将其存储在 Cocoa 运行时中。 默认情况下,list_artifacts集合中列出的所有工件都会经过验证。 使用skip-sign-artifact-type文本属性,可跳过对指定工件类型(例如:log、report、documentation)的图像签名验证。 以下示例代码演示了如何从 Cloud Object Storage 下载一个构建产物,并将其保存到 Cocoa 运行时中:#!/usr/bin/env bash export SECRET_PATH="/config/ibmcloud-api-key" . "${ONE_PIPELINE_PATH}"/iam/get_token SKIP_SIGN_ARTIFACTS_TYPE="$(get_env skip-sign-artifact-type "")" IFS=';' read -ra ARTIFACT_LIST <<<"$SKIP_SIGN_ARTIFACTS_TYPE" list_artifacts | while IFS= read -r artifact; do type="$(load_artifact "$artifact" "type")" if [[ ! "${ARTIFACT_LIST[@]}" =~ "$type" ]] && [[ "$type" != "image" ]]; then inventory_entry="$(load_artifact "$artifact" "inventory-entry")" inventory_entry=${inventory_entry///artifacts/$WORKSPACE} artifact_url=$(jq -r .'app_artifacts.artifact_url' ${inventory_entry}) echo "downloading the artifact ${artifact_url}" curl -H "Authorization: bearer ${IAM_ACCESS_TOKEN}" --output outputfile ${artifact_url} save_file "${artifact}" outputfile fi done
验证工件
在工件验证过程中,将用户提供的 GPG 公用密钥导入到 GPG 密钥环中。 将验证 list_artifacts 集合中列出的所有工件。 该阶段尝试从清单中检索签名并执行以下验证:
gpg --verify "${signature}" "${artifactName}"
如果签名有效并使用提供的公用密钥进行验证,那么阶段将记录证据并将阶段标记为成功。