GitHub 在 9 月 16 日发布更新:GitHub Enterprise Cloud 的企业管理员现在可以通过企业安装的 GitHub App,为已有的经典 Personal Access Token(PAT)和 SSH Key 批量完成 SSO 授权。一次请求最多覆盖 50 个组织,开发者不必再逐个打开组织页面手动确认。
这不是“让一个 App 代替用户登录”的宽泛自动化,而是给企业凭据授权流程增加了一条有边界的管理通道。App 只能在企业显式开启委托后调用 API,GitHub 会先检查企业、凭据所有者和目标组织之间的关系,而且请求中使用的是 PAT 的标识或 SSH Key 指纹,不是凭据秘密本身。对平台团队来说,真正值得关注的是:SSO 授权终于可以跟凭据轮换、组织变更和审计流程连在一起。
为什么 SSO 授权会成为自动化的瓶颈
在启用 SSO 的企业里,凭据通常同时受到两套关系约束:一套是用户或服务账号拥有这个 PAT、SSH Key;另一套是这个凭据是否被允许访问某个组织。凭据本身没有变化,组织范围却可能随着团队拆分、项目迁移和新组织加入而变化。
过去,成员需要对每个组织分别授权。组织数量一多,手工操作就会带来三个问题:
- 轮换难以准时完成:团队为了避免重复点选,可能拖延 PAT 或 SSH Key 的替换。
- 授权状态难以盘点:平台团队很难用统一方式知道一个自动化凭据已经覆盖哪些组织。
- 人员操作无法稳定复现:离职、值班交接或服务账号没有交互式登录能力时,授权流程容易卡住。
这也是为什么 GitHub 的公告把“避免为了躲开轮换而使用长生命周期令牌”作为这次更新的背景。自动化的目标不是让凭据活得更久,而是让凭据可以按计划轮换,同时把新凭据的授权动作做成可记录、可重试的流程。
新能力的工作方式
GitHub 新增的是企业级凭据授权 API。企业安装的 GitHub App 可以用一个企业安装访问令牌发起请求,指定凭据标识、凭据类型和目标组织列表:
1 | POST /enterprises/{enterprise}/credential-authorizations |
如果授权对象是 SSH Key,凭据类型改为 ssh_key,标识使用已经验证的、用户所有的 SSH Key 的 SHA-256 指纹。这里的 credential_id 是 PAT 的编号,不是 PAT 字符串;请求也不应该携带任何令牌秘密。
GitHub 在处理请求前会检查至少三类关系:
- 目标组织确实属于指定企业;
- 凭据所有者是每一个目标组织的成员;
- 企业使用企业级 SSO,且当前凭据类型满足授权条件。
已有有效授权的组织会被安全跳过,不需要脚本先把所有状态拉下来再自行去重。这让 API 具备了比较好的幂等性:轮换任务失败后可以重试,而不会因为重复授权把正常状态当成异常。
权限边界并不在 API 调用本身
要启用这条路径,企业需要主动打开“Allow GitHub Apps to authorize credentials”设置,并满足一组前置条件:
| 项目 | 要求 |
|---|---|
| 产品范围 | GitHub Enterprise Cloud |
| SSO 形态 | 企业级 SSO |
| App 归属 | 企业或企业内组织拥有的 GitHub App |
| App 权限 | Enterprise credentials 写权限 |
| API 身份 | 企业安装访问令牌,不是用户令牌或组织安装令牌 |
| 凭据范围 | 经典 PAT,或已验证且用户所有的 SSH Key |
这里最容易被忽略的是安装访问令牌。官方文档要求 App 使用企业安装访问令牌调用 API,组织安装令牌、用户访问令牌和个人 PAT 都不支持这条授权操作。安装令牌本身默认只存活一小时,平台服务应当在需要时用 App 的 JWT 和企业安装信息重新生成,而不是把安装令牌当成长效秘密保存。
另外,Enterprise credentials 写权限不是“只允许给这个 API”的临时开关。它代表 App 可以改变企业凭据的 SSO 授权状态,因此应该单独设置 App、单独保存私钥,并把调用日志与变更工单关联起来。不要把这个权限附加到已经拥有大量仓库或组织管理能力的通用 App 上。
把它放进凭据轮换流水线
这项功能最适合服务账号、自动化机器人和跨多个组织运行的构建系统。一个较稳妥的轮换流程可以拆成下面几步:
flowchart LR
A[创建新 PAT 或 SSH Key] --> B[保存凭据秘密]
B --> C[记录 token ID 或 SHA-256 指纹]
C --> D[校验组织清单与成员关系]
D --> E[App 批量授权 SSO]
E --> F[执行只读 API 与 Git 拉取测试]
F --> G[切换业务使用的新凭据]
G --> H[撤销旧凭据授权并删除旧秘密]
顺序上要先让新凭据可用,再撤销旧凭据。对于 GitHub Actions、构建服务和发布平台,还应该在切换前做一次真实路径验证:用实际运行环境调用 API、读取仓库或完成一次最小化的 Git 操作,而不是仅检查授权接口返回成功。
如果企业新增了组织,也可以在组织加入企业后触发一次授权同步。同步任务应以企业和组织的当前状态为准,不要只根据上一次运行时保存的列表做追加。组织可能已被移出企业,成员资格也可能发生变化,服务应把授权失败记录为需要人工处理的状态。
标识符、秘密和审计记录要分开
这次 API 的一个重要设计是“使用标识符,不传凭据秘密”。但这不代表标识符可以随意暴露。PAT 的 token ID 和 SSH Key 指纹仍然能够帮助定位一个高权限凭据,应该和组织清单、操作者、调用时间以及授权结果一起纳入访问控制。
建议至少记录以下字段:
- 企业、App、安装 ID 和调用者身份;
- PAT 的 token ID 或 SSH Key 的 SHA-256 指纹;
- 请求中的目标组织,以及 GitHub 实际授权或跳过的组织;
- API 版本、请求结果、失败原因和重试次数;
- 关联的轮换工单、凭据版本和切换时间。
凭据秘密应该继续存放在专门的秘密管理系统里,不能写入 GitHub App 日志、CI 输出或普通业务数据库。脚本也不应通过“打印当前 token”来确认流程成功,而应使用最小权限的实际调用验证新凭据是否已经能完成目标操作。
撤销路径要提前设计
自动授权如果没有对应的撤销路径,就容易变成新的权限积累入口。官方文档提供了撤销企业委托授权的 API;关闭“允许 GitHub Apps 授权凭据”设置,只会阻止新的授权,不会自动撤销已经存在的授权。已经建立的授权仍需显式撤销,或者等凭据被删除、撤销、用户失去组织成员资格时失效。
因此,平台团队至少应该准备两种撤销动作:按某个 App 的委托记录撤销,以及在安全事件中批量撤销企业范围内的委托授权。批量撤销属于异步操作,系统要记录排队结果并在后台任务结束后复核,而不是把 202 Accepted 直接当成所有授权已经消失。
这项能力不适合解决什么问题
它解决的是“同一个凭据需要在多个 SSO 组织获得授权”的流程摩擦,不是凭据治理的全部答案。以下问题仍然需要单独处理:
- 新建凭据时如何审批权限范围和过期时间;
- 服务账号是否真的需要经典 PAT,能否改用更细粒度的凭据或 GitHub App;
- SSH 私钥如何托管、轮换和在疑似泄露后快速吊销;
- 组织成员资格变化后,授权同步如何收敛;
- 机器人执行失败时,谁能看到日志并完成复核。
如果一个任务只需要访问少数仓库,优先选择范围更小、生命周期更短的身份方式。批量授权降低的是操作成本,不应成为扩大长期凭据权限的理由。
结语
GitHub Enterprise Cloud 这次更新的核心,不是多了一个“批量点确认”的接口,而是把 SSO 凭据授权从人工页面操作推进到了企业级身份自动化。它同时给出了比较清晰的安全边界:企业主动开启、App 使用专门权限、GitHub 校验企业和成员关系、调用只引用凭据标识而不传秘密。
对平台团队来说,比较合适的落地顺序是先建立凭据清单和轮换流程,再为一个低风险服务账号试点,最后把授权、验证、切换、撤销和审计串成完整闭环。这样,自动化带来的不是更多“默认有效”的权限,而是一条更容易观察、更容易回滚的授权路径。