# 第十九章:SPIFFE — 通用工作负载身份框架 > "人有身份证,机器也需要身份证。SPIFFE 就是机器世界的身份证标准。" ```{mermaid} mindmap root((SPIFFE)) SPIFFE ID trust domain path 格式规范 SVID X.509-SVID JWT-SVID 短生命周期 Trust Bundle 信任根 联邦信任 Workload API Unix Socket gRPC 自动轮换 设计哲学 平台无关 自动化 零配置 ``` ## 19.1 工作负载身份的挑战 在云原生时代,机器身份(工作负载身份)面临独特的挑战: | 挑战 | 描述 | |------|------| | 数量级 | 工作负载数量远超人类用户(数十万级) | | 动态性 | 容器随时创建和销毁,IP 地址不固定 | | 异构性 | 跨 Kubernetes、VM、裸机、多云 | | 凭证管理 | 手动管理证书/密钥不可扩展 | | 信任建立 | 如何证明"这个进程确实是它声称的服务" | ``` 传统方式的问题: ┌──────────┐ ┌──────────┐ │ Service A │───▶│ Service B │ │ │ │ │ │ 如何证明 │ │ 如何验证 │ │ "我是A"? │ │ "它是A"? │ └──────────┘ └──────────┘ 方案1: 硬编码密钥 → 泄露风险、无法轮换 方案2: 环境变量 → 容易被窃取 方案3: K8s Secret → 仅限 K8s、明文存储 方案4: Vault → 需要先认证才能获取密钥(鸡生蛋问题) 方案5: SPIFFE ✅ → 自动化、短生命周期、平台无关 ``` ## 19.2 SPIFFE 是什么 SPIFFE(Secure Production Identity Framework For Everyone)是一套开源标准,为工作负载提供统一的身份框架。它是 CNCF 毕业项目。 SPIFFE 定义了三个核心规范: 1. **SPIFFE ID**:工作负载的唯一身份标识 2. **SVID**:可验证的身份文档 3. **Workload API**:工作负载获取身份的接口 ## 19.3 SPIFFE ID SPIFFE ID 是一个 URI,格式为: ``` spiffe://trust-domain/path 示例: spiffe://example.org/ns/production/sa/web-server spiffe://example.org/region/us-east/service/payment spiffe://bank.com/department/trading/app/risk-engine ``` | 组成部分 | 说明 | 示例 | |---------|------|------| | scheme | 固定为 spiffe | spiffe:// | | trust domain | 信任域,类似 DNS 域名 | example.org | | path | 工作负载路径,自由定义 | /ns/prod/sa/web | ### Trust Domain 设计原则 ``` 推荐的 Trust Domain 命名: ✅ prod.example.com — 生产环境 ✅ staging.example.com — 预发布环境 ✅ cluster1.example.com — 按集群划分 ❌ example.com — 太宽泛 ❌ my-app — 不像域名 路径设计建议: /ns/{namespace}/sa/{service-account} — Kubernetes 风格 /region/{region}/service/{service-name} — 按区域划分 /env/{environment}/app/{app-name} — 按环境划分 ``` ## 19.4 SVID — 可验证身份文档 SVID(SPIFFE Verifiable Identity Document)是工作负载的"身份证",有两种形式: ### X.509-SVID 最常用的形式,基于 X.509 证书: ``` Certificate: Subject: O=SPIRE Subject Alternative Name: URI: spiffe://example.org/ns/prod/sa/web-server ← SPIFFE ID Issuer: O=SPIRE, CN=SPIRE CA Validity: Not Before: 2024-01-01 00:00:00 UTC Not After: 2024-01-01 01:00:00 UTC ← 1小时有效期! Public Key Algorithm: ECDSA P-256 ``` 关键特性: - SPIFFE ID 存储在证书的 **SAN URI** 字段 - **短生命周期**(通常 1 小时),自动轮换 - 用于 **mTLS** 双向认证 ### JWT-SVID 基于 JWT 的身份文档,适用于 L7 场景: ```json { "alg": "ES256", "kid": "key-1", "typ": "JWT" } . { "sub": "spiffe://example.org/ns/prod/sa/web-server", "aud": ["spiffe://example.org/ns/prod/sa/api-server"], "exp": 1709510400, "iat": 1709506800 } . [signature] ``` ### X.509-SVID vs JWT-SVID | 维度 | X.509-SVID | JWT-SVID | |------|-----------|----------| | 用途 | mTLS(L4) | HTTP Header(L7) | | 验证方式 | TLS 握手 | Token 验证 | | 受众绑定 | ❌ | ✅(aud claim) | | 代理穿透 | ✅ | ✅ | | 性能 | 高(TLS 层) | 中(应用层) | | 适用场景 | 服务间直连 | API Gateway、L7 代理 | ## 19.5 Trust Bundle Trust Bundle 是信任域的根证书集合,用于验证 SVID: ``` Trust Domain: example.org Trust Bundle: [Root CA Certificate] 验证流程: 1. Service A 出示 X.509-SVID 2. Service B 用 example.org 的 Trust Bundle 验证证书链 3. 验证 SAN 中的 SPIFFE ID 4. 信任建立 ✅ ``` ## 19.6 Workload API Workload API 是工作负载获取 SVID 的标准接口: ``` ┌──────────────┐ Unix Domain Socket ┌──────────────┐ │ 工作负载 │◀────────────────────────▶│ SPIRE Agent │ │ (应用进程) │ /run/spire/sockets/ │ │ │ │ agent.sock │ 自动签发 │ │ 获取 SVID │ │ 自动轮换 │ │ 获取 Bundle │ │ 缓存管理 │ └──────────────┘ └──────────────┘ ``` ```go // Go 示例:使用 Workload API 获取 SVID import "github.com/spiffe/go-spiffe/v2/workloadapi" ctx := context.Background() source, err := workloadapi.NewX509Source(ctx, workloadapi.WithClientOptions( workloadapi.WithAddr("unix:///run/spire/sockets/agent.sock"), ), ) defer source.Close() // 获取 SVID svid, err := source.GetX509SVID() fmt.Printf("SPIFFE ID: %s\n", svid.ID) fmt.Printf("证书有效期: %s\n", svid.Certificates[0].NotAfter) // 用 SVID 建立 mTLS 连接 tlsConfig := tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeID( spiffeid.RequireID(spiffeid.Must("example.org", "/ns/prod/sa/api-server")), )) ``` ## 19.7 SPIFFE 与传统方案对比 | 方案 | 平台无关 | 自动轮换 | 短生命周期 | 零配置 | 标准化 | |------|---------|---------|-----------|--------|--------| | K8s ServiceAccount | ❌ | ❌ | ❌ | ✅ | ❌ | | AWS IAM Role | ❌ | ✅ | ✅ | ❌ | ❌ | | 手动 mTLS | ✅ | ❌ | ❌ | ❌ | ❌ | | HashiCorp Vault | ✅ | ✅ | ✅ | ❌ | ❌ | | **SPIFFE/SPIRE** | **✅** | **✅** | **✅** | **✅** | **✅** | ## 19.8 小结 - **SPIFFE** 是工作负载身份的开放标准(CNCF 毕业项目) - **SPIFFE ID** 格式:`spiffe://trust-domain/path` - **SVID** 有两种形式:X.509-SVID(mTLS)和 JWT-SVID(L7) - **短生命周期**(1小时)+ **自动轮换** = 大幅降低凭证泄露风险 - **Workload API** 通过 Unix Socket 提供零配置的身份获取 - SPIFFE 是**平台无关**的,可以跨 K8s、VM、多云使用