跳到主要内容
版本:3.9.x

验证 API7 镜像签名

为了保护软件供应链安全,API7 的 Docker 容器镜像遵循行业最佳实践,使用开源工具 Cosign 进行签名。所有签名都存储在公共 Docker Hub 仓库 api7/notary 中。我们的构建和发布流程使用 GitHub Actions,并利用 GitHub 的 OIDC (OpenID Connect) 身份对镜像进行签名,从而提供了额外的可信认证层。

通过验证镜像签名,你可以确信:

  • 真实的来源:镜像是由 API7 的官方 GitHub Actions 工作流构建和发布的。
  • 完整性:镜像从发布到拉取过程中的任何环节都没有被任何第三方修改。

本指南将向你展示验证 API7 镜像签名的过程。

前置条件

  1. 安装 Cosign 以验证容器镜像签名。
  2. 安装 regctl 以获取容器镜像的摘要(digest)。

验证签名

要验证 API7 容器镜像签名,你需要配置签名仓库的位置,检索镜像摘要,并使用 Cosign 验证签名。

设置签名仓库

设置 COSIGN_REPOSITORY 环境变量以指定镜像存储签名的位置:

export COSIGN_REPOSITORY=api7/notary

获取镜像摘要

每个 Docker 镜像都有一个唯一的 SHA-256 摘要,代表其内容的快照。为了确保你验证的是确切的镜像内容(而不是可变的标签),请使用 regctl 检索镜像摘要:

regctl manifest digest api7/api7-ee-3-gateway:3.9.1

你应该会看到镜像的摘要:

sha256:61a531d7ca8339712888bfdf7ad7af6d63f0e423e466818be96f0aaa3fc89578

运行 Cosign 验证

获取镜像摘要后,运行 cosign verify 命令来验证镜像签名。该命令将验证签名、证书链和相关的声明(claims):

cosign verify \
'api7/api7-ee-3-gateway:3.9.1@sha256:61a531d7ca8339712888bfdf7ad7af6d63f0e423e466818be96f0aaa3fc89578' \
--certificate-oidc-issuer='https://token.actions.githubusercontent.com' \
--certificate-identity-regexp='https://github.com/api7/api7-ee-3-gateway/.github/workflows/push-release-image.yaml'

如果验证成功,你将看到类似于以下的响应,其中包括已执行检查的摘要:

Verification for index.docker.io/api7/api7-ee-3-gateway@sha256:61a531d7ca8339712888bfdf7ad7af6d63f0e423e466818be96f0aaa3fc89578 --
The following checks were performed on each of these signatures:
- The cosign claims were validated
- Existence of the claims in the transparency log was verified offline
- The code-signing certificate was verified using trusted certificate authority certificates

该命令还输出一个 JSON 对象,其中包含有关签名的详细元数据,例如构建工作流、代码库和触发事件:

[
{
"critical":{
"identity":{
"docker-reference":"index.docker.io/api7/api7-ee-3-gateway"
},
"image":{
"docker-manifest-digest":"sha256:61a531d7ca8339712888bfdf7ad7af6d63f0e423e466818be96f0aaa3fc89578"
},
"type":"cosign container image signature"
},
"optional":{
"1.3.6.1.4.1.57264.1.1":"https://token.actions.githubusercontent.com",
"1.3.6.1.4.1.57264.1.2":"push",
"1.3.6.1.4.1.57264.1.3":"757582d641f7bdcad3c1299cb7da113224f4f383",
"1.3.6.1.4.1.57264.1.4":"Build And Push Release Docker Image",
"1.3.6.1.4.1.57264.1.5":"api7/api7-ee-3-gateway",
"1.3.6.1.4.1.57264.1.6":"refs/tags/v3.9.1",
"Bundle":{
"SignedEntryTimestamp":"MEUCIQCj1Xupisdx7YosnqpdByE6pGpeMzeRcBF3H6+wgK0txgIgCImsRsV+tG+96tVkGiXcr6iNifirhk7Q4lW+S3tuOX4=",
"Payload":{
"body":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiI4ZjAyMzdlYzRhNTBlMzkwNWFjYWQ1ZWExYzE4ODFmMzMyZWM4NmE3Y2Y5ZGQ0OWU2NmQwYmQyMTVjMDBiZDlhIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FWUNJUUQrM1U2T1NFYnpoVk9qZlFFWnRSWmZpYlgrSWVyWWpxWEMzb1U1ZWozYTBBSWhBTENYSG1yRXUvUXhHVUlncTdSZDQ2cVhCQkVwQS9qbm03ZTJtR1B6TE8yeiIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVaEJha05EUW05cFowRjNTVUpCWjBsVlN5ODNUVmM0YTNodlYyUjFkRTFCYnpkMVFYUmtOVFpZY21aTmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDFVUVRSTlJFMTVUa1JOZVZkb1kwNU5hbGwzVFZSQk5FMUVUWHBPUkUxNVYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZoUzJzelRFVmlRa0psVWtsaFNsWTFVbGw1YVZod1dtRXZVUzlaVEU1bVVtbFhOVTBLZFhweGJFbFVka1ptUWxCQ1YyRTNjRXBLZFZoTGEwOVZSVmxZT0VOUmJHRXlNMmg1TkN0MlNXdFliRmRITm05elRVdFBRMEpoWTNkbloxZHFUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZwVGtONUNtcFVVMUY1YzJsTU9XbE5NbU50Ym5wd1ltbEtNVTl2ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDJObldVUldVakJTUVZGSUwwSkhaM2RhYjFwcllVaFNNR05JVFRaTWVUbHVZVmhTYjJSWFNYVlpNamwwVERKR2QyRlVZM1paV0VKd1Rua3hiQXBhVXpCNlRGZGthR1JIVmpOWldHdDJURzFrY0dSSGFERlphVGt6WWpOS2NscHRlSFprTTAxMlkwaFdlbUZETVhsYVYzaHNXVmhPYkV4WGJIUlpWMlJzQ2t4dWJHaGlWM2hCWTIxV2JXTjVPVEJaVjJSNlRETlpla3hxYTNWTlZFRTFRbWR2Y2tKblJVVkJXVTh2VFVGRlFrSkRkRzlrU0ZKM1kzcHZka3d6VW5ZS1lUSldkVXh0Um1wa1IyeDJZbTVOZFZveWJEQmhTRlpwWkZoT2JHTnRUblppYmxKc1ltNVJkVmt5T1hSTlFrbEhRMmx6UjBGUlVVSm5OemgzUVZGSlJRcENTRUl4WXpKbmQwNW5XVXRMZDFsQ1FrRkhSSFo2UVVKQmQxRnZUbnBWTTA1VVozbGFSRmt3VFZkWk0xbHRVbXBaVjFGNldYcEZlVTlVYkdwWmFtUnJDbGxVUlhoTmVrbDVUa2RaTUZwcVRUUk5la0Y0UW1kdmNrSm5SVVZCV1U4dlRVRkZSVUpEVGtOa1YyeHpXa05DUW1KdFVXZFZTRlo2WVVOQ1UxcFhlR3dLV1ZoT2JFbEZVbl",
"integratedTime":1767842673,
"logIndex":804165791,
"logID":"c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d"
}
},
"Issuer":"https://token.actions.githubusercontent.com",
"Subject":"https://github.com/api7/api7-ee-3-gateway/.github/workflows/push-release-image.yaml@refs/tags/v3.9.1",
"githubWorkflowName":"Build And Push Release Docker Image",
"githubWorkflowRef":"refs/tags/v3.9.1",
"githubWorkflowRepository":"api7/api7-ee-3-gateway",
"githubWorkflowSha":"757582d641f7bdcad3c1299cb7da113224f4f383",
"githubWorkflowTrigger":"push"
}
}
]

证书身份和工作流

--certificate-identity-regexp 参数确保签名证书与预期的 GitHub Actions 工作流匹配。这可以验证镜像是通过正确的自动化流程构建的。

由于每个 API7 镜像都是由特定的工作流发布的,因此你必须使用匹配的正则表达式进行验证。使用下表查找你正在验证的镜像证书对应的 --certificate-identity-regexp 值:

镜像名称证书身份正则表达式 (Certificate Identity RegExp)
api7/api7-ee-3-gatewayhttps://github.com/api7/api7-ee-3-gateway/.github/workflows/push-release-image.yaml
api7/api7-ee-3-integratedhttps://github.com/api7/api7ee-3-control-plane/.github/workflows/release.yaml
api7/api7-ee-dp-managerhttps://github.com/api7/api7ee-3-control-plane/.github/workflows/release.yaml
api7/api7-ee-developer-portalhttps://github.com/api7/api7ee-3-control-plane/.github/workflows/release.yaml
api7/api7-ee-developer-portal-fehttps://github.com/api7/api7ee-developer-portal/.github/workflows/release.yml