摘要
- -07 要求每枚 JWT 不得携带一个以上的受众,除非平台无法发出多枚凭证,或工作负载无法影响受众;-06 对单一受众只使用了 SHOULD。
- 风险不是抽象的“令牌泄露”,而是接收端之间的冒用:拿到同一枚 bearer 令牌的任何一方,都可能把它提交给另一个接受方。
- 能力例外回执应记录隔离为何不可能、完整接收端图、令牌寿命与可达范围、各端验证、补偿控制、复核时间以及退出例外的条件。
设想一个 Pod 把同一枚 projected service-account token 用在两处:先交给 Kubernetes API 服务器执行基础设施操作,再交给外部身份提供方换取另一种访问令牌。两个接收端都是真实、合法的系统,也都因此持有这枚 bearer 凭证。只要 aud 允许这两种用途,外部身份提供方就能把令牌交回 API 服务器,并以该工作负载的身份出现。
这条路径不需要中间人,不需要日志泄漏,也不要求攻击者攻破签发方。问题恰恰来自一次“成功”的验证:本来只负责认证工作负载的接收端,因为凭证没有保留接收端之间的边界,获得了在另一端冒充它的能力。
这就是 2026 年 9 月 22 日上传的 draft-ietf-wimse-workload-identity-practices-07 最关键的操作变化。它目前仍是计划归入 Informational 的活跃 Internet-Draft。Datatracker 显示的状态是 AD Evaluation::AD Followup,动作持有人为 Charles Eckel。这是审阅状态,不是 IESG 批准,不是 RFC,也不是任何产品已经部署或违规的证据。
从 SHOULD 到 MUST,改变的是默认责任
-06 已经给出了正确方向。其通用要求写道,凭证应尽可能缩小范围;只要平台支持多枚凭证,工作负载就应为每个资源或身份提供方获取不同凭证。受众章节则说,每枚 JWT 应只携带一个受众。
-07 把边界改为规范性要求:凭证 MUST 尽可能收窄;直接访问平台资源的凭证 MUST 只覆盖该资源;用于身份联合的凭证 MUST 以身份提供方为唯一受众;除明确定义的能力例外外,每枚 JWT MUST NOT 携带多个受众。
这不是把大写字母加粗那么简单。建议允许实现方在权衡后选择其他方案;要求则把隔离设为默认条件,偏离者必须说明为何落入例外。-07 还补上了完整的风险机制:同一 aud 中列出的任何 relying party,都可能把令牌交给另一方并获得非预期访问。
因此,受众不是验证器里无关痛痒的路由标签。它列出了 bearer 凭证可以在哪些地方“开口说话”。每增加一个接受方,也增加了一个能够把同一凭证拿到其他接受方重放的持有者。
Kubernetes 把抽象风险变成一条回路
Kubernetes 能够为 service account 发出多枚 projected token,并分别指定受众和寿命。-07 用这项能力拆开三条路径:访问 API 服务器、访问集群内其他资源,以及与外部身份提供方联合。三处所用令牌必须不同,受众也必须不同。
这比“API 服务器会检查 aud”更严格。若两个接收端接受同一份 bearer 材料,一端的本地校验无法保护另一端。外部身份提供方完全可以正确检查 issuer、签名、过期时间和受众,同时仍持有 API 服务器也会接受的令牌。每个局部检查都通过,系统边界依然可能失败。
SPIFFE 示例采用相同规则:供内部资源使用的 JWT-SVID 与供外部身份提供方联合使用的 JWT-SVID,必须是受众不同的两枚令牌。云平台示例里,-06 对内部访问与外部 STS 联合使用 SHOULD/SHOULD NOT;-07 改成 MUST/MUST NOT。不同平台背后的不变量,都是接收端图。
例外承认能力缺口,并不把两种设计说成等价
草案没有假装所有平台都能遵守。有的平台每个工作负载只能签发一枚凭证,有的平台不允许工作负载影响受众。-07 因此允许在“无法取得多枚凭证”或“无法影响受众”时,不执行单一受众要求。
但这不是为了集成方便预留的出口。上下文明确说,共用一枚跨场景凭证的部署不能依靠 audience scoping 限制影响范围,必须把寿命缩到平台允许的最短,限制能够接触凭证的组件,并把每个接收端都视为能够在其他接受端冒充工作负载的一方。
此时的安全状态并不等价。接收端图变大,控制从密码学上的受众隔离,转移到时间、组件访问、网络路径、验证纪律和监测。补偿控制可能合理,但必须以“缺少能力的补偿”被看见,不能被一枚绿色合规标志抹平。
-07 对 proof of possession 也采取同样做法。平台和 relying party 都不支持 PoP 时,较短寿命、更严格的受众范围和额外网络控制,从 SHOULD 变成 MUST。缩短寿命只能压缩重放窗口,不能把 bearer token 变成只允许原发送方使用的凭证。
在令牌真正使用之处保存能力例外回执
一张能力例外回执,应把具体部署决定固定在可复核的边界上:
| 回执字段 | 应保留的证据 |
|---|---|
| 签发能力 | 平台、issuer、确切版本,以及能否发出多枚凭证 |
| 受众控制 | 工作负载能否请求或影响 aud,并附 API 或配置证据 |
| 预期用途 | 平台 API、内部资源、身份联合或外部资源 |
| 凭证标识 | 非秘密、不可逆的指纹或代次编号,绝不保存 bearer 值 |
| 接收端图 | 全部接受方,以及接收端之间可能互相提交的路径 |
| 寿命 | 请求与实际 TTL、续期行为、撤销或失效路径 |
| 可达范围 | 能接触或携带凭证的组件、挂载、sidecar、代理、日志与出口 |
| 验证 | 各接收端对 issuer、audience、type、PoP 与网络条件的检查 |
| 例外理由 | 缺少哪项平台能力,为何无法分离凭证 |
| 补偿措施 | 较短寿命、组件隔离、网络控制、监测与告警 |
| 复核 | 责任人、决定时间、下次复核、修正触发器与退出条件 |
这里的指纹必须是非秘密、单向的。回执绝不能成为把 bearer token 原文塞进工单的理由。它的作用,是把风险决定绑定到当时覆盖的凭证代次、接收端和控制措施。
回执还要区分“不能”与“没有做”。如果签发方支持独立凭证,只是集成为了省事而复用,能力例外并不适用。如果后续版本加入了受众控制,退出条件就已经出现。没有复核时间的例外,很容易悄悄变成架构。
BTW 先前的《工作负载凭证不是工作负载》梳理了从启动到最终结果的八类证明。本文刻意只处理其中一个更窄的问题:这一枚 bearer token 能在哪些接收端代表工作负载,又有哪些接收端能把它拿去向别人发言?
来源与边界
主要依据包括 Datatracker 的 -07 记录、文档历史、不可变的-07 纯文本和用于比较的-06 纯文本。把协调文件与运行现实分开的写作原则,来自最小初始规范、本地化未来决策与自愿采用。
这些来源能证明文档状态、规范文本和安全机制,不能证明现实中已经发生事故,不能提供完整实施普查,也不能证明某个具名运营方违规。能力例外回执是 Daniel Kade 提出的编辑性控制建议,并非 WIMSE 草案中的强制字段。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance

