GitHub Actions artifact attestations 的构建来源核对方法
来源:17golang原创
时间:2026-10-26 11:45:15 474浏览 收藏
发布二进制或容器镜像时,标签和校验和只能回答“拿到的文件是不是这一份”,不能完整说明“它由哪个仓库、哪条工作流产生”。GitHub Actions 的 artifact attestations 用签名证明把构建产物和来源信息绑在一起,再用 GitHub CLI 按仓库、签名工作流和来源提交核对。
官方地址:https://docs.github.com/en/actions/how-tos/secure-your-work/use-artifact-attestations
- attestation 主要证明产物与来源仓库、工作流和提交的关系,不等于完整记录 runner 镜像。
- 生成证明至少要给工作流写入 OIDC 和 attestation 权限,动作放在产物生成之后。
- 在线核对优先用 API 获取证明;离线场景要同时保存 bundle 和 trusted root,并重新审视仓库改名边界。
先划清 attestation 能证明什么
我第一次把它接进发布流水线时,最容易混淆的是“来源证明”和“执行环境证明”。证明里有产物摘要、来源仓库、提交、签名工作流等信息,适合回答“这个文件是不是由指定来源构建出来的”。但社区讨论也指出,runner 名称、runner 组和具体镜像并不天然等价于这条来源链;不要把一次验证通过写成“所有构建环境都可信”。
| 核对对象 | 适合回答 | 不要过度推断 |
|---|---|---|
| Repository | 产物绑定到哪个仓库 | 仓库当前名称一定没有改过 |
| Signer workflow | 哪条工作流签了证明 | 工作流内部每一步都不可变 |
| Source ref | 来源分支或提交范围 | runner 镜像和硬件配置 |
| Runner environment | 部分环境属性 | 完整机器审计记录 |

在构建工作流中生成来源证明
先让构建步骤生成文件,再在同一个 job 的后面调用 actions/attest。权限要放在工作流或 job 的可见配置里,避免用过大的默认权限掩盖实际依赖。
permissions:
# 让 attestation 动作向 Sigstore 请求短期签名身份
id-token: write
# 允许把证明保存到 GitHub 的 attestation 存储
attestations: write
# 只有需要关联产物存储记录时才保留这项权限
artifact-metadata: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build release binary
run: make release
- name: Create build provenance
uses: actions/attest@v4
with:
# 绑定刚刚生成的文件,而不是随意绑定工作区目录
subject-path: dist/my-app
这里的关键不是把 YAML 粘贴得越复杂越好,而是确保 subject-path 指向最终发布物。若发布的是容器镜像,应按官方动作的容器模式配置并确认镜像已经推送到 registry;文件产物则优先使用明确的路径。新接入时先把权限和产物路径写成最小闭环,再考虑 SBOM 或自定义 predicate。
用 GitHub CLI 按身份核对产物
验证时至少给出仓库或组织范围。对生产发布,我更愿意把签名工作流也锁定,因为“来自这个仓库”比“来自这条受控工作流”宽得多。必要时再加来源提交,形成可审查的三层约束。
# 用仓库、签名工作流和来源提交收窄验证范围 gh attestation verify dist/my-app \ --repo example/acme-app \ --signer-workflow example/acme-app/.github/workflows/release.yml \ --source-ref refs/tags/v1.4.0 # 需要交给门禁程序判断时,输出结构化结果 gh attestation verify dist/my-app \ --repo example/acme-app \ --format json \ --jq '.[].verificationResult.signature.certificate.sourceRepositoryIdentifier'
默认 predicate 是 SLSA provenance;如果系统使用的是 SBOM 或自定义声明,要显式指定 --predicate-type,否则验证命令和团队理解可能不一致。若采用 reusable workflow,真正签名的是可复用工作流,检查项应随之改用 --signer-workflow 或 --signer-repo。

离线环境保存 bundle 与可信根
隔离环境不能直接访问 GitHub API 时,在线机器先下载 attestation bundle,再把可信根材料一并带入离线区。两个文件缺一不可:bundle 是针对产物的证明,trusted root 用来验证签名链。
# 在线机器:按仓库下载产物对应的证明包 gh attestation download dist/my-app --repo example/acme-app # 在线机器:导出验证签名链需要的可信根材料 gh attestation trusted-root > trusted_root.jsonl # 离线机器:指定本地 bundle 和 trusted root 进行验证 gh attestation verify dist/my-app \ --repo example/acme-app \ --bundle PATH/TO/BUNDLE.jsonl \ --custom-trusted-root trusted_root.jsonl
离线核对有一个容易漏掉的边界:--repo 会和证明证书里记录的仓库名称比较,但它不能自动判断仓库后来是否改名,也不能阻止另一个仓库复用旧名称。对高价值发布物,还应在线取得仓库 ID,在离线 JSON 结果中比对 sourceRepositoryIdentifier。
把核对动作放进发布门禁
可以把下面这张清单放进 release job 的最后一步:
- 产物路径是否固定,摘要是否对应最终上传的文件或镜像。
- 权限是否只包含本次证明所需的
id-token、attestations和必要的元数据权限。 - 验证是否至少限定仓库,生产环境是否继续限定签名工作流和来源 ref。
- 离线交付是否把 bundle、trusted root 和核对结果一起归档。
- 是否把 provenance 与 runner 镜像、硬件和临时环境的证据分开管理。
这样做的结果是:attestation 负责“产物从哪里来”,发布门禁负责“哪些来源可以进入下一阶段”,而 runner 和构建环境仍由独立的执行记录补足。职责拆开后,验证失败时更容易判断是产物不匹配、签名身份不对,还是门禁策略过窄。
相关问题
只有仓库参数够不够?
低风险内部构建可以先用 --repo。正式发布建议继续限制签名工作流,并在需要时限制来源 ref,避免同一仓库里其他工作流也能满足条件。
为什么验证通过仍不能说明 runner 镜像可信?
来源证明关注产物、仓库、提交和签名身份;具体 runner 镜像、组和机器配置属于另一类执行环境证据,不能由一次 provenance 验证自动替代。
仓库改名后离线验证要怎么做?
不要只看旧仓库名称。在线查询当前仓库 ID,离线使用 JSON 输出读取证书中的来源仓库 ID,再把两个 ID 做比对。
-
Golang · Go教程 | 3个月前 | CI/CD · gitHub actions · Go教程 · 持续集成 · Go 持续集成 CI Go test GitHub Actions self-hosted runner 自托管 runner340 收藏
-
351 收藏
-
196 收藏
-
395 收藏
-
文章 · 软件教程 | 2星期前 | github · 故障排查 · CI/CD · gitHub actions · GitHub Actions 失败任务 Job workflow run 重跑任务162 收藏
-
310 收藏
-
492 收藏
-
106 收藏
-
122 收藏
-
162 收藏
-
210 收藏
-
290 收藏
-
334 收藏
-
166 收藏
-
394 收藏
-
188 收藏
-
340 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习