2. SPIFFE标准精讲
SPIFFE 的核心价值在于把“工作负载是谁”从模糊的部署描述中抽离出来,变成一个可验证、可跨平台传递的身份标识。要真正用好 SPIRE,必须先理解 SPIFFE 标准定义的四个基础构件:SPIFFE ID 的 URI 结构、信任域(Trust Domain)的语义边界、SVID 的类型与生命周期,以及 Federation 与 Bundle 如何把多个信任域连接起来。本节围绕这四个构件展开,重点说明它们的结构、约束和实际使用方式。
SPIFFE ID:身份的唯一命名
SPIFFE ID 是一个 URI,格式固定为 spiffe://<trust domain>/<path>。其中 spiffe 是 scheme,trust domain 是信任域名称,path 是域内路径。例如:
spiffe://corp.example.com/ns/payment/sa/checkout
spiffe://corp.example.com/ns/frontend/sa/web
spiffe://edge.example.net/workload/telemetry-agent
信任域部分只允许小写字母、数字、点、连字符和下划线,不能包含端口、路径或查询参数;路径部分以 / 开头,可包含多级段,但不得出现空段、. 或 ..。SPIFFE ID 本身不携带密钥、过期时间或权限信息,它只是一个命名,必须配合 SVID 才能被验证。这一点常被误解:拿到一个 SPIFFE ID 字符串并不等于获得了身份,只有持有对应私钥并出示由信任域签发的 SVID,才能证明“我拥有这个 ID”。
路径的语义由使用方约定,SPIFFE 标准不做强制规定。工程上常见两种组织方式:一种按 Kubernetes 的 ns/<namespace>/sa/<serviceaccount> 映射,另一种按业务层级如 /env/prod/svc/order。选择哪种取决于授权策略的粒度,但一旦确定就应保持稳定,因为 SPIFFE ID 会被写入策略、日志和审计记录,频繁变更会带来迁移成本。
信任域:签发与验证的边界
信任域是 SPIFFE ID 中 spiffe:// 之后的第一段,它定义了一个独立的签发与验证边界。同一个信任域内的所有 SVID 由该域的信任锚(Trust Anchor)签发,域内工作负载默认互信;跨域通信则必须通过 Federation 显式建立信任。信任域名称通常使用组织可控的 DNS 名称,如 corp.example.com,但 SPIFFE 不要求它真的可解析,只要求全局唯一且稳定。
信任域的关键语义有三点。第一,它是策略的作用域:授权规则通常写成“信任域 A 的某路径可以访问信任域 B 的某服务”。第二,它是密钥材料的隔离单位:不同信任域的 CA 私钥相互独立,一个域被攻破不会自动波及另一个域。第三,它是 Bundle 的归属单位:每个信任域维护一份 Bundle,包含本域及所有联邦域的信任锚公钥。理解这三层语义,才能在设计多集群、多环境身份体系时正确划分信任域,而不是把所有工作负载塞进一个域里。
SVID:可验证身份文档的类型与生命周期
SVID 是 SPIFFE Verifiable Identity Document 的缩写,是 SPIFFE ID 的可验证载体。标准定义两种类型:X.509-SVID 和 JWT-SVID。X.509-SVID 是一张 X.509 证书,SPIFFE ID 放在 SAN 扩展的 URI 字段中,用于 mTLS 场景;JWT-SVID 是一个 JWT,SPIFFE ID 放在 sub 声明中,aud 声明指定接收方,用于无法建立 TLS 的场景,如 HTTP 头传递或消息队列。
两种 SVID 的生命周期都由 SPIRE Agent 管理,典型流程如下:工作负载通过 Workload API 请求身份,Agent 校验其选择器(如 Unix UID、Kubernetes Pod 标签)后,向 SPIRE Server 申请签发,Server 返回短期证书或 JWT,Agent 将其交给工作负载。X.509-SVID 默认有效期约 1 小时,JWT-SVID 更短,通常 5 到 15 分钟。到期前 Agent 会自动轮换,工作负载通过 Workload API 的流式接口持续接收新 SVID,无需重启。
验证 X.509-SVID 时,接收方需要做三件事:用信任域 Bundle 中的 CA 公钥验证证书链;检查证书未过期;从 SAN URI 中提取 SPIFFE ID 并据此做授权判断。验证 JWT-SVID 时,则用 Bundle 中对应信任域的 JWT 签名公钥验签,并校验 aud 是否为自己、exp 是否未过期。两者都不依赖网络位置或 IP,这正是 SPIFFE 能跨云、跨集群工作的原因。
Federation 与 Bundle:跨信任域的信任传递
当两个信任域需要互信时,使用 SPIFFE Federation。其机制是:域 A 和域 B 各自把对方的信任锚公钥加入自己的 Bundle,并对外发布自己的 Bundle。SPIRE 通过 Federation Endpoint 暴露 Bundle,支持两种模式:https_web 通过标准 HTTPS 提供 Bundle,https_spiffe 则要求请求方出示本域 SVID 做双向认证,安全性更高。配置联邦关系时,需要指定对端信任域名称、Bundle 端点 URL 和端点使用的 profile。
Bundle 是一个包含若干 X.509 根证书和 JWT 签名公钥的集合,按信任域组织。它有两个关键属性:一是可增量更新,SPIRE 会定期拉取对端 Bundle,CA 轮换后旧公钥会在一段时间内保留,避免正在使用的 SVID 突然失效;二是只包含公钥,不包含任何私钥,因此可以安全地通过 HTTPS 分发。下图展示了两个信任域通过 Federation 交换 Bundle 后,工作负载跨域验证 SVID 的完整链路。
图中可以看到,Bundle 交换是双向的:A 把 CA-A 公钥给 B,B 把 CA-B 公钥给 A。此后工作负载 A 向工作负载 B 出示 SVID A 时,B 用自己 Bundle 中的 CA-A 公钥验签,验证通过后从 SAN URI 提取 spiffe://corp.example.com/ns/pay/sa/checkout,再按策略决定是否放行。整个过程不需要 A 和 B 共享私钥,也不需要预先配置 IP 白名单。
实际配置要点与判断依据
在 SPIRE 中建立联邦关系,通常需要在 Server 配置中声明对端信任域和 Bundle 端点,例如:
federation {
federates_with "edge.example.net" {
bundle_endpoint {
address = "https://spire-b.edge.example.net:8443"
profile = "https_spiffe"
}
}
}
配置完成后,可用 spire-server bundle list 查看本域 Bundle 中是否已包含对端 CA 公钥,用 spire-server federation list 确认联邦关系状态。判断联邦是否生效,最直接的方法是让域 A 的工作负载向域 B 发起 mTLS 连接:若握手成功且对端能解析出正确的 SPIFFE ID,说明 Bundle 已同步、SVID 验签通过;若握手失败,应依次检查 Bundle 端点可达性、对端 CA 公钥是否在本地 Bundle 中、SVID 是否过期,以及 aud 或 SAN 是否匹配。
把四个构件串起来看:SPIFFE ID 回答“是谁”,信任域回答“由谁签发、边界在哪”,SVID 回答“如何证明”,Federation 与 Bundle 回答“如何跨边界互信”。四者缺一不可,且都围绕一个原则——身份不依赖网络位置,只依赖可验证的密码学材料。理解这一点,后续在 SPIRE 中配置注册条目、选择器、节点证明和联邦策略时,就能清楚每一步在整体链路中的位置。