最后更新于 2026 年 9 月 11 日,数据核实自 GitHub Actions OIDC 参考文档OIDC REST API 文档Apple Developer API Key 文档

GitHub 官方文档确认:2026 年 7 月 15 日后创建的仓库,默认使用包含 owner ID 与 repository ID 的不可变 sub 格式;GitHub Enterprise Server 不在这项默认变更范围内。你的 workflow 文件可能完全没有改动,但云端角色仍会因主体不匹配而拒绝登录。修复顺序应固定为:先读取真实 OIDC token,再更新云端信任策略,最后验收远程 Mac 的发布权限。不要为了恢复流水线,直接回退到长期云密钥。

这篇文章适合三类人:

  • 管理 GitHub Actions OIDC、云端角色和企业身份策略的平台工程团队。
  • 维护自托管 Mac Runner、Xcode 构建及生产发布链路的研发效能负责人。
  • 准备重命名、转移仓库或统一 OIDC 模板的安全与身份治理负责人。
01

先用 subject 指标判断故障边界

2026 年 7 月 15 日改变了什么

旧仓库默认可能继续使用名称型 subject:

repo:example-org/mobile-app:ref:refs/heads/main

新建仓库,或主动启用不可变 subject claims 的仓库,可能使用:

repo:example-org@123456/mobile-app@789012:ref:refs/heads/main

GitHub 官方给出的不可变格式为:

repo:OWNER@OWNER-ID/REPO@REPO-ID:ref:refs/heads/BRANCH

其中的 owner ID 与 repository ID 用于降低组织名称或仓库名称回收后产生相同 subject 的风险。仓库重命名或转移后,也可能切换到不可变格式。旧仓库则保持原格式,除非管理员主动选择加入。该能力不适用于 GitHub Enterprise Server。(GitHub OIDC 参考)

你需要同时检查以下字段:

  • iss:是否仍为预期的 GitHub OIDC 签发者。
  • aud:是否与云平台或内部网关要求的 audience 一致。
  • sub:云端信任策略真正匹配的主体。
  • repository_id:当前仓库的稳定 ID。
  • owner_idrepository_owner_id:当前组织或所有者的 ID。
  • environmentrefjob_workflow_ref:分支、Environment 或可复用工作流上下文是否改变。

不要只根据仓库网页地址猜格式。你应在脱敏测试仓库中读取一次实际 token,保留字段名、格式和必要的 ID 片段,不要把完整 JWT 发送到工单或聊天工具。

失败日志要和 token 放在同一份证据包里

单独保存“权限不足”或“无法换取令牌”的日志,无法证明是 subject 变化。最小证据包应包括:

  1. 失败 Job 的时间、仓库、分支和 Environment。
  2. 云端返回的拒绝原因。
  3. 脱敏后的 issaudsubrepository_id 与 owner ID。
  4. 当前云端角色信任条件的版本。
  5. 最近一次仓库重命名、转移或 OIDC 模板变更记录。

OIDC token 可能包含仓库、工作流、运行编号和时间窗口等信息。日志中还可能出现云端角色、内部资源或账号标识。排查时应只提取诊断所需字段,避免把完整令牌当作普通调试文本保存。

02

信任策略必须匹配实际声明

GitHub Actions OIDC 失效时,最常见的错误不是 workflow 没有请求 token,而是云端仍在匹配旧的 sub。例如,旧策略允许:

repo:example-org/mobile-app:ref:refs/heads/main

而实际 token 已经变为:

repo:example-org@123456/mobile-app@789012:ref:refs/heads/main

这两个主体并不相同。你只修改 workflow,云端仍会拒绝。

AWS、Azure、Google Cloud Platform 和 HashiCorp Vault 的配置语法不同,但判断逻辑一致:信任端必须匹配 token 中真实出现的 subaud。对于使用不可变格式的仓库,云端条件也必须同步包含 owner ID 与 repository ID。

组织模板与仓库状态要分开核对

你需要把仓库分成三类:

  • 新建仓库:2026 年 7 月 15 日后创建,默认可能使用不可变格式。
  • 旧仓库主动加入:管理员通过设置或 REST API 主动启用不可变 subject。
  • 组织模板影响:组织级或仓库级模板改变了 sub 的结构。

GitHub REST API 支持查询和管理组织、仓库的 OIDC subject 模板,并提供 use_immutable_subject 选项。变更前,先建立受影响清单:

  • 仓库名称与 repository_id
  • 所属组织与 owner ID。
  • 绑定的云端角色。
  • 分支和 Environment。
  • 使用的可复用工作流。
  • 对应的自托管 Mac Runner 组。

经验提醒: 先把云端主体改成组织级通配符,确实可能让流水线恢复,但这不是修复,只是扩大了受信范围。正确做法是先生成新 token,再收敛到明确的仓库、Environment 或工作流主体。

03

用指标对照表确定修复位置

下面的对照表用于判断应该修改哪里。不要把“能换到短期令牌”直接等同于“发布链路已经安全”。

故障指标 观察结果 应采取的动作 不应采取的动作
iss 不正确 签发者不是预期 GitHub OIDC 地址 检查运行环境、代理和 token 获取方式 放宽云端 issuer
aud 不匹配 audience 与云平台要求不同 统一 audience 参数和云端条件 删除 audience 条件
sub 从名称格式变为 ID 格式 包含 owner ID、repository ID 更新云端主体并保留分支或 Environment 限制 使用 repo:* 全量通配
sub 出现 Environment 主体上下文包含环境名 检查 Environment 保护规则与审批 改成允许所有分支
包含 job_workflow_ref 使用可复用工作流身份 同时限制调用仓库和工作流引用 只按组织名匹配
repository_id 不符合预期 仓库已转移、复制或环境错误 重新核对仓库清单和绑定角色 沿用旧仓库名称
token 正确但换取失败 信任策略以外存在权限或网络问题 检查角色权限、endpoint、时间和网关日志 立刻恢复长期访问密钥

可复用工作流适合企业统一部署模板,但会引入 job_workflow_ref 等新的判断维度。你应先在云端创建匹配条件,再通过 GitHub REST API 修改 subject 模板。如果云端条件还未同步,新的 token 可能暂时无法被接受。

04

权限边界不能被“修复”冲掉

GitHub Actions Job 只应在确实需要时声明:

permissions:
  id-token: write
  contents: read

id-token: write 允许 Job 请求 OIDC token,但不会自动授予云资源写权限。实际访问范围仍由云端角色、主体条件、分支、Environment 和工作流上下文共同决定。

建议你建立四列验收记录:

  • 允许主体:明确仓库、分支、Environment 或可复用工作流。
  • 拒绝主体:非目标仓库、非保护分支、未审批 Environment 和非可信 PR。
  • 令牌范围:issuer、audience、subject、有效时间和云端角色。
  • 审批证据:策略版本、测试运行编号、失败日志和负责人确认。

不要为了排障,把 sub 改成组织级通配符,也不要取消 Environment 审批。对企业工作流而言,分支保护、Environment 审批和最小权限应同时存在,而不是在恢复流水线时互相取舍。

05

远程 Mac 与 Apple 签名身份必须分层

OIDC 适合让 GitHub Actions 向支持联合身份的云平台或内部服务换取短期访问令牌。它不能自动替代 Apple Distribution 证书、Developer ID 证书或 App Store Connect API 私钥。

App Store Connect API 使用 API Key 生成 JWT。Apple 官方文档说明,API Key 由公开部分和下载后的私钥组成,私钥用于签署授权请求;如果怀疑私钥泄露,应立即撤销对应 API Key。(Apple API Key 文档)

Apple 的云管理证书可以减少部分本地证书维护工作,但它仍然属于 Apple Developer 账户体系,并不意味着任何 GitHub Job 都能接触签名能力。Apple 文档说明,新签名请求出现时,系统会在证书到期前 90 天自动创建新的云管理证书;这不等于 OIDC 可以替代 Apple 的证书和私钥模型。(Apple 云管理证书说明)

自托管 Mac Runner 的三层隔离

你可以按以下方式划分:

  1. 普通构建节点:运行单元测试、编译和非发布归档,不保存生产签名 Keychain。
  2. 云资源访问节点:允许 id-token: write,只用于交换短期云令牌,不读取 Apple 私钥。
  3. 生产签名节点:只接受受保护分支和经过审批的 Environment,限制 Runner group,任务完成后清理工作区与临时凭证。

长期共享 Mac 的优点是成本和维护路径简单。缺点是工作区、进程、Keychain 和缓存可能残留。一次性 Runner 能降低残留风险,但你仍需验证底层主机是否真正清理。专用发布 Mac 的隔离效果最好,但需要承担节点闲置、故障接管和运维成本。

GitHub 官方提醒,自托管 Runner 不保证运行在一次性、干净的虚拟机中,恶意工作流代码可能持续影响主机。组织级 Runner 还可能承接多个仓库的任务,因此应通过 Runner group 限制可访问的组织与仓库。公开仓库尤其不适合直接使用带敏感权限的自托管 Runner。(GitHub 自托管 Runner 安全说明)

如果你正在评估远程 Mac 作为发布节点,可以先阅读 远程 Mac 构建节点 PoC 与恢复测试,重点检查节点隔离、任务路由和故障接管,而不是只比较硬件参数。

06

用受控测试完成生产放量

建议按以下 7 步执行:

  1. 冻结扩大影响的改动:暂时不要启用全组织模板,也不要把信任主体改成宽泛通配符。
  2. 选择脱敏测试仓库:使用与生产相同的 OIDC 模板、Environment 和可复用工作流结构。
  3. 读取真实 token:记录 issaudsubrepository_id、owner ID、refjob_workflow_ref
  4. 核对 GitHub 状态:查询仓库或组织的 OIDC 设置,确认是否启用了 immutable subject claims。
  5. 更新云端信任条件:先增加准确的新主体,保留分支、Environment 和 audience 限制。
  6. 执行正反测试:允许的分支和 Environment 必须成功,未授权仓库、分支和未审批环境必须失败。
  7. 验收 Mac 发布边界:确认 Runner 重启后能重新接收任务,工作区已清理,签名 Keychain 不被云权限 Job 读取,备用节点能接管。

生产记录至少保留模板配置、信任策略版本、失败与成功日志、测试仓库、运行编号和回退条件。令牌、API 私钥、证书私钥、账号标识和内部资源名称必须脱敏。

如果团队还没有稳定的节点分层,可以把 团队共享 Mac 权限管理 作为权限设计的延伸阅读。重点不是让所有开发者共享同一台主机,而是让构建、云访问和签名任务拥有不同的进入条件。

07

FAQ:企业身份修复中的五个高频判断

云端突然拒绝 GitHub Actions 的身份请求,应该先查哪里?

最先检查实际 token 的 sub 是否已经从名称型格式变为包含 owner ID 与 repository ID 的不可变格式。仓库创建时间、重命名、转移、组织模板和 Environment 都可能影响声明。不要先改 workflow 或恢复长期密钥,应同时核对 issaudsubrepository_id 与 owner ID。

仓库改名后,云角色里的主体条件怎样同步?

先运行受控工作流,保存新 token 的脱敏 sub,再修改云端角色主体条件。分支、Environment 和 audience 条件应继续保留。新策略验证成功后,再删除旧主体,避免新旧名称都能访问同一个生产角色。

新格式为何把所有者和仓库的数字 ID 放进 sub

GitHub 在 2026 年 7 月 15 日后为新建仓库默认采用不可变 subject claims,目标是避免组织或仓库名称被回收后产生相同 subject。新格式把 owner ID 和 repository ID 放入 repo 段,因此名称变化不会单独决定身份。

OIDC 短期令牌能不能取代 Apple 的签名凭证?

不能直接替代。OIDC 只负责向支持联合身份的云平台或内部服务换取短期令牌。Apple Distribution、Developer ID、App Store Connect API 等身份仍有独立的证书、私钥或 API Key 要求,生产签名权限应继续放在隔离节点。

怎样把自托管 Mac Runner 上的云访问和签名权限拆开?

至少拆分测试构建、云资源访问和生产签名三层。非可信 PR 不应接触签名节点;云 OIDC Job 不应自动读取签名 Keychain;生产发布只允许受保护分支、Environment 审批和限定 Runner group 进入,任务结束后清理工作区。

08

修复 OIDC 后,别把三种身份重新放回同一台机器

当前常见做法是让一台长期共享的 Mac 同时承担云端访问、Xcode 构建和生产签名。它的缺点很具体:工作区与缓存容易残留,Runner 重启后的恢复路径不清晰,云端短期令牌与 Apple 私钥可能出现在同一台主机上,故障排查时还容易通过放宽权限快速“修好”而留下长期越权。

更稳妥的方式,是先用专用远程 Mac 做小范围试点,把云身份、构建任务和签名 Keychain 分层,再验证节点清理、重启恢复和备用接管。如果你不想立即购买多台实体设备,可以参考 VpsMesh 的 Mac 租赁方案,把它作为临时发布节点或隔离 PoC 环境;但长期高负载、必须接触物理接口或需要完全自主管理硬件的团队,仍应评估自购 Mac 的总拥有成本。