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,无需重启。

SVID 的有效期短是设计目标而非缺陷:短周期把密钥泄露的窗口压缩到分钟级,同时迫使系统依赖自动轮换而非人工分发。若业务无法承受轮换带来的连接重建,应在应用层实现证书热加载,而不是延长 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 的完整链路。

SPIFFE Federation:Bundle 交换与跨域 SVID 验证 信任域 A:corp.example.com SPIRE Server A CA-A 私钥 · 签发 X.509/JWT-SVID Bundle A CA-A 公钥 + CA-B 公钥 工作负载 A spiffe://corp.example.com/ns/pay/sa/checkout X.509-SVID A SAN URI = SPIFFE ID A · 有效期约 1h 信任域 B:edge.example.net SPIRE Server B CA-B 私钥 · 签发 X.509/JWT-SVID Bundle B CA-B 公钥 + CA-A 公钥 工作负载 B spiffe://edge.example.net/workload/telemetry X.509-SVID B SAN URI = SPIFFE ID B · 有效期约 1h Bundle A → B Bundle B → A 出示 SVID A 用 Bundle B 中的 CA-A 公钥验签 Federation Bundle 交换 跨域出示 SVID 对端 Bundle 验签

图中可以看到,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 和所有授权策略同时失效,等同于重建整个身份体系。规划阶段应把信任域当作长期稳定的命名空间来对待。

把四个构件串起来看:SPIFFE ID 回答“是谁”,信任域回答“由谁签发、边界在哪”,SVID 回答“如何证明”,Federation 与 Bundle 回答“如何跨边界互信”。四者缺一不可,且都围绕一个原则——身份不依赖网络位置,只依赖可验证的密码学材料。理解这一点,后续在 SPIRE 中配置注册条目、选择器、节点证明和联邦策略时,就能清楚每一步在整体链路中的位置。