Workload Identity:别再把云上身份塞进 Secret 里了
Posted on 四 19 3月 2026 in Journal
| Abstract | Workload Identity:别再把云上身份塞进 Secret 里了 |
|---|---|
| Authors | Walter Fan |
| Category | learning note |
| Version | v1.2 |
| Updated | 2026-03-19 |
| License | CC-BY-NC-ND 4.0 |
Workload Identity:别再把云上身份塞进 Secret 里了
短大纲
- 先讲一个老场景:应用要访问云资源,长期 AK/SK 往配置文件、环境变量或 Kubernetes Secret 里一塞
- workload identity 在干什么:让 Pod、容器这类“工作负载”也有可验证、可审计、能轮换的身份
- 拆开看:谁发证、信任链怎么走、短期令牌怎么换、云侧角色怎么挂上
- Kubernetes 里怎么落地,以及我见过的几个典型坑
- 文末留一张明天就能照着勾的检查清单
有些系统的安全设计,第一眼就像把家门钥匙贴在门口,旁边再贴一行:"请勿乱动,这是生产环境。"
云上应用要碰对象存储、消息队列、数据库、KMS,都正常。卡壳往往在一句:你怎么证明你是你。 很多团队的第一反应也实在:配一对 Access Key,塞进 Secret,挂进 Pod,收工。上线那天都觉得效率高;出事那天又集体想起还有个词叫零信任。
workload identity 要对付的,就是这个。
别被名字唬住。说人话就是:别给应用发一张长期身份证复印件,让它在跑起来的时候,凭自己所在的环境,换一张短期、能验真、权限也收着的通行证。
表面看是“凭证怎么发”换了个做法,骨子里是信任模型换了:从“谁拿到那串字符谁就是你”,变成“只有这个工作负载、在这个环境、这样跑起来,才临时拿到这点权限”。差别不小。前者像银行卡和密码塞同一个钱包;后者像刷脸加动态码,过期作废。
什么是 Workload Identity
如果把 IAM 里的人类用户身份想成“工牌”,workload identity 就是给程序、容器、Pod、虚拟机、函数实例也做一张工牌。
它回答的问题其实很朴素,但一答错就麻烦:
这个正在跑的工作负载,凭什么去动某个云资源?
老路子常见就三条:
- 代码里写死
- 配置文件或环境变量里灌长期凭证
- Kubernetes Secret 里存云账号密钥,挂给 Pod
三条路有一个共同点:先有凭证,再谈身份。
系统不怎么在乎“你是谁”,只在乎“你手里有没有那串东西”。字符串在谁手里,谁就能冒充你。开发机能用,测试环境能用,离职同事备份里那份也能用。密钥一漏,后面通常就不太好收场。
而 workload identity 的思路正好反过来:
- 先确认工作负载的真实身份
- 再基于这个身份签发短期令牌或临时凭证
- 最后通过 IAM、STS 或 federation 机制换取访问目标资源的权限
所以它的核心不是“发 token”,而是建立工作负载到云权限之间的可信映射。
为什么它越来越重要
早些年机器就那几台,凭证塞在机器里,土是土点,秩序还能糊住。现在不一样了:
- 容器短命,这个 Pod 今天在,明天可能换节点
- CI/CD、扩缩容、Serverless,实例不停地起停
- 业务拆成一堆服务,各自要碰不同的云资源
- 合规和审计也会追问:谁、在什么时候、为什么能访问这个
这种时候,长期凭证就像办公室那把万能钥匙。平时谁都觉得顺手,一丢就得整层换锁。
更烦的是,长期凭证特别容易养出一堆“先凑合”的习惯:
- 权限开大点,免得以后再申请
- 几个服务共用一套密钥,省得配来配去
- 凭证不过期,免得轮换搞挂线上
- 出事先改 Secret,根因慢慢再说
短期看是省事,长期是欠债,利息还不低。
Workload Identity 的本质:把“运行时上下文”变成“可信身份”
理解 workload identity,抓住一句就够:
身份不看你存了什么,而看你正在以什么身份跑。
背后一般有四块拼图:
1. 工作负载本身
比如一个 Kubernetes Pod、一个 VM 上的进程、一个 serverless function 实例。
2. 身份提供者(Identity Provider)
负责证明这个工作负载是谁。常见实现包括 Kubernetes Service Account Token、OIDC issuer、SPIFFE/SPIRE、云厂商自己的 metadata service。
3. 信任桥梁
把“工作负载身份”映射到“云权限”。这一步通常由 STS、federation、assume role 之类的机制完成。
4. 资源授权系统
也就是 IAM policy、RBAC、resource policy 这些真正决定“能不能访问”的地方。
把它串起来,大概是这样:
- Pod 先拿到一个能证明自己身份的 token
- 这个 token 由可信 issuer 签发,比如 Kubernetes OIDC issuer
- 云平台验证 token 的签名、受众、过期时间、subject 等信息
- 验证通过后,把这个 Pod 映射到某个云角色
- 云角色再发放短期访问凭证
- 应用拿着短期凭证访问对象存储、消息队列、数据库等资源
注意,第一张 token 多半只是介绍信,后面换出来的临时权限才是门禁卡。值钱的通常是后者。
一个典型场景:Kubernetes 里的对象存储访问
假设你有一个日志归档服务,跑在 Kubernetes 里。它需要把处理后的文件上传到对象存储。
最传统的做法是:
- 创建一个云账号密钥
- 把 AK/SK 放进 Kubernetes Secret
- Pod 启动时挂载 Secret
- SDK 从环境变量里读取密钥
这套打法的问题,随便拎一条都够写半页复盘:
- Secret 被误导出,密钥泄漏
- 多个命名空间复用同一套密钥,权限边界消失
- 密钥长期不轮换,谁也不敢动
- 审计日志只能看到“某个账号访问了资源”,看不到具体是哪个 Pod、哪个服务
- 开发环境复制生产配置,顺手把生产权限带过去了
换成 workload identity 后,思路会变成:
- 给这个服务绑定一个专用 Kubernetes Service Account
- 在云平台里建立信任关系:允许这个 Service Account 对应的身份换取某个云角色
- 给云角色最小权限,只允许写入指定 bucket 或 prefix
- Pod 启动后,通过挂载的 service account token 去换短期凭证
- SDK 自动使用临时凭证访问对象存储
收益不只在“少了一个 Secret”:
- 权限跟着工作负载走,不跟着静态密钥走
- 凭证短,泄漏能用的窗口小
- 审计能落到具体 workload identity
- 边界清楚些,一个服务一套身份,少共用万能钥匙
这套机制到底怎么工作
不同平台名字很多,AWS 叫 IAM Roles for Service Accounts,GCP 叫 Workload Identity,Azure 有 Workload Identity Federation,Kubernetes 社区还有 SPIFFE/SPIRE。名字不同,套路很像。
第一步:给工作负载一个可验证的身份声明
在 Kubernetes 里,这通常是 Service Account Token。现代 Kubernetes 支持带 audience、过期时间、issuer 的 projected service account token,比早年那种“几乎永久有效”的 token 安全得多。
这个 token 里通常会包含:
iss:谁签发的sub:主体是谁,比如某个 namespace 下的某个 service accountaud:这个 token 是给谁看的exp:什么时候过期
像工作证:光挂个牌子不够,得能对上发证单位、姓名、有效期、给谁用。
第二步:建立信任关系
云平台需要先声明:
- 我信任这个 issuer
- 我只接受某些 audience
- 我只允许某些 subject 映射到某些角色
这一步是整个系统的命门。信任面铺大了,等于给陌生人留门;收太紧,业务又跑不动。安全工程常常不酷,更像拧水龙头:不是拧越大越好,是刚好够用最难。
第三步:交换短期凭证
工作负载拿着自己的身份 token 去找 STS 或等价服务,请求:
这是我的身份证明,请给我一张能访问某些资源的临时票据。
STS 验证通过后,返回短期凭证。它通常有明确的 TTL,比如 15 分钟、1 小时。过期了就得重新换。
这一步的价值非常现实:
- 泄漏了也只能用一小段时间
- 可以随时撤销信任关系
- 不需要手工轮换长期密钥
- SDK 往往能自动刷新,应用代码更干净
第四步:按最小权限访问资源
最后,真正的授权还是靠 IAM policy。workload identity 不是魔法,它不会自动让权限变合理。它只是把“谁在申请权限”这件事做得更可信。
如果你给这个角色配了 *:*,那它依然会非常危险。只是这次危险得更现代一点。
它解决了什么问题,又没解决什么问题
技术文最怕把一样东西写成救世主。workload identity 有用,但不是万能药。
它擅长解决的
1. 消灭长期静态凭证
这是最直接的收益。少一个长期 Secret,通常就少一类高频事故。
2. 缩小泄漏影响面
短期凭证比长期密钥好控 blast radius,这是实打实的。
3. 提升审计能力
你能更清楚地知道:哪个 workload、在哪个 namespace、以什么角色访问了什么资源。
4. 更适合云原生环境
Pod、Job、函数实例都很短命,workload identity 天生适合这种动态环境。
它解决不了的
1. 应用自身被攻陷
攻击者要是已经能在 Pod 里执行代码,照样可能滥用当前进程手里的临时凭证。workload identity 把窗口缩短了,挡不住“被攻破的进程用自己该有的权限搞事”。
2. 过度授权
身份可信,权限照样可以胡来。最小权限还是你自己的功课,平台不会替你写好。
3. 东西向访问控制
服务之间怎么互相认证,未必由 workload identity 单独解决。很多场景还需要 mTLS、service mesh、SPIFFE ID 等机制配合。
4. 组织流程问题
如果团队没有权限治理流程,谁都能随手创建高权限角色,那再好的身份机制也会被用成“自动发放万能钥匙机”。
Kubernetes 落地时最容易踩的坑
下面这些坑,现场里见得不少。
坑一:一个 namespace 里所有服务共用默认 Service Account
这几乎是“我知道不对,先这样吧”的经典现场。
问题在于,一旦多个服务共用同一个 Service Account,它们在云侧就很难做到精细隔离。最后你会发现:明明只是一个导出报表的小服务,却继承了读写生产存储桶的能力。
建议:一个服务一个专用 Service Account,重要服务甚至按环境拆分。
坑二:信任条件写得太宽
比如只信任某个集群 issuer,却没有限制 namespace、service account name、audience。结果就是,只要集群里别的 Pod 能拿到合法 token,也可能换到不该有的角色。
建议:把条件收紧到 namespace + service account + audience,必要时再加更多 claim 约束。
坑三:还在手工注入云凭证,和 workload identity 混着用
于是会出现一种诡异状态:你以为已经在用 workload identity,SDK 却先从环境变量里捞到长期密钥。安全改造最怕这种“看起来升级了”。
建议:迁移时明确 credential provider chain,验证应用实际使用的是哪种凭证来源。
坑四:忽略 token audience
很多人只关心 token 能不能签发,不关心 aud。但 audience 是防止 token 被错误复用的重要约束。给 A 服务看的 token,不应该被 B 服务拿去冒用。
建议:显式配置并校验 audience,不要全靠默认值。
坑五:没有观察和告警
身份系统一出问题,业务侧往往先看到 403,而不是一条漂亮的安全告警。日志和指标跟不上,排查就像黑屋里找眼镜,眼镜其实还架在鼻梁上。
建议:监控 STS 调用失败率、token 刷新失败、角色假设失败、权限拒绝日志。
一个更通用的理解:它像公司门禁,不像保险箱密码
有人第一次听 workload identity,会当成“又一种管 Secret 的办法”。不算全错,但窄了。
我更喜欢这么比:
- 长期密钥像保险箱密码,知道的人都能开
- workload identity像公司门禁:卡是临时的、能吊销,还能记下谁、几点、进了哪道门
差别主要在好不好治理。
安全不止“挡住攻击”,还包括:
- 能不能撤
- 能不能查账
- 能不能收权限
- 能不能自动轮换
- 规模大了之后秩序还在不在
workload identity 的长处,是它更经得起治理。它不保证绝对安全,只是让系统少赌一点运气。
多云环境下的常见实现映射
虽然各家云厂商命名不同,但可以用同一套思路理解:
| 平台 | 常见名称 | 工作负载身份来源 | 临时权限交换机制 |
|---|---|---|---|
| AWS | IAM Roles for Service Accounts (IRSA) | Kubernetes OIDC + Service Account Token | STS AssumeRoleWithWebIdentity |
| GCP | Workload Identity / Workload Identity Federation | Kubernetes SA 或外部 OIDC/SAML 身份 | STS + Service Account Impersonation |
| Azure | Azure AD Workload Identity | Kubernetes OIDC + Federated Identity Credential | Microsoft Entra ID token exchange |
| 通用方案 | SPIFFE/SPIRE | SPIFFE ID、X.509 SVID、JWT-SVID | 与 IAM/STS 或自定义授权系统集成 |
理解这张表的重点不是记名字,而是记住共同模式:工作负载先证明自己,再换取短期权限。
如果你要开始做,建议按这个顺序推进
别一上来全量改。安全改造最怕理想很丰满,回滚很频繁。
第一步:找出所有长期云凭证
盘点这些地方:
- Kubernetes Secret
- CI/CD 变量
- Helm values
- Terraform state 或变量文件
- 应用配置中心
- 开发者本地
.env文件
先把现状摸清楚。很多团队的问题不是没有方案,而是不知道自己到底藏了多少把钥匙。
第二步:按服务划分身份边界
问自己三个问题:
- 这个服务到底需要访问什么资源?
- 它需要读、写,还是管理权限?
- 它能不能和别的服务共用身份?
大多数情况下,答案应该是:不能共用。
第三步:先挑低风险服务试点
比如日志上传、报表导出、只读查询这类。支付、核心交易、生产控制面别当头一炮。勇敢不是拿生产当试验田。
第四步:建立最小权限策略
把资源范围和动作范围都收紧。例如:
- 只允许访问某个 bucket
- 只允许写入某个 prefix
- 只允许读取某个 secret path
- 只允许调用某个 topic 或 queue
第五步:验证“真的没在用静态凭证”
这是迁移里最容易漏的一步。你需要确认:
- 环境变量里没有残留 AK/SK
- Secret 没再被挂载
- SDK 实际拿到的是临时凭证
- 凭证过期后能自动刷新
第六步:补齐审计和告警
至少要能回答:
- 哪个 workload 在申请临时凭证?
- 失败率如何?
- 哪些角色最常被使用?
- 哪些权限拒绝是误配,哪些可能是异常行为?
一个简单的决策原则:什么时候该用,什么时候别用
适合用 workload identity 的场景
- 运行在 Kubernetes、VM、Serverless 等动态环境中
- 需要访问云资源或平台 API
- 希望消除长期凭证
- 对审计、合规、权限边界有要求
- 服务数量多,手工管理密钥已经开始失控
不要指望它单独解决的场景
- 服务间细粒度双向认证
- 进程内机密保护
- 已被攻陷主机上的横向移动防御
- 复杂的人类用户授权流程
说白了,它是身份这块的地基,不是整栋安全楼。
明天就能做的检查清单
如果你只想带走最实用的部分,抄这份就够了:
- [ ] 盘点所有存放云凭证的地方,尤其是 Kubernetes Secret 和 CI/CD 变量
- [ ] 为每个服务创建独立的 Service Account,不再共用默认账号
- [ ] 在云平台侧建立精确的 trust policy,限制 issuer、subject、audience
- [ ] 给每个 workload 绑定最小权限角色,拒绝“先给大权限跑起来”
- [ ] 验证 SDK 实际使用的是临时凭证,而不是残留的静态密钥
- [ ] 监控 token 交换失败、权限拒绝、异常访问模式
- [ ] 为高价值服务做一次“凭证泄漏演练”,看看 blast radius 到底有多大
总结
workload identity 动的不只是“凭证怎么发”,更是系统凭什么相信一段正在跑的代码。
身份从静态字符串,变成运行时能验的东西;权限从长期攥在手里,变成按需换一张短的;安全从“千万别漏”,往前挪半步到“漏了也别太惨”。
不算花哨,云原生里很朴素的一条:
别把信任押在一串长期不变的字符串上。
系统要是还把云凭证塞进 Secret,再拿 RBAC 当心理按摩,有点像现金锁抽屉,门口再贴张“闲人免进”。有用没用?有一点。安慰成分?也不低。
最后附一张思维导图,方便快速回顾:
@startmindmap
* Workload Identity
** 为什么需要
*** 消灭长期静态凭证
*** 缩小泄漏影响面
*** 提升审计能力
*** 适配云原生动态环境
** 核心机制
*** Workload
**** Pod
**** VM
**** Function
*** Identity Provider
**** OIDC
**** Service Account Token
**** SPIFFE
*** Trust Federation
**** STS
**** Assume Role
*** IAM Authorization
**** Least Privilege
** Kubernetes 落地
*** 独立 Service Account
*** 限制 issuer subject audience
*** 验证 SDK 凭证来源
*** 监控 token 交换失败
** 常见误区
*** 共用默认账号
*** Trust policy 过宽
*** 静态凭证与临时凭证混用
*** 忽略 audience
** 适用边界
*** 不是银弹
*** 不能替代最小权限设计
*** 不能单独解决服务间认证
@endmindmap
扩展阅读
- Kubernetes Service Account Token Projection: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
- Google Cloud Workload Identity Federation: https://cloud.google.com/iam/docs/workload-identity-federation
- GKE Workload Identity: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity
- AWS IAM Roles for Service Accounts: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
- Azure AD Workload Identity for Kubernetes: https://azure.github.io/azure-workload-identity/docs/
- SPIFFE and SPIRE: https://spiffe.io/docs/latest/spiffe-about/overview/
本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。