第二十章:SPIRE — SPIFFE 的参考实现
“SPIRE 让 SPIFFE 从标准变为现实,让工作负载身份从理论走向生产。”
mindmap
root((SPIRE))
Server
CA Manager
Registry
DataStore
Node Attestation
Agent
Workload API
Cache Manager
Workload Attestation
SDS
证明机制
Node Attestation
Workload Attestation
部署
Kubernetes
裸机
Docker
20.1 SPIRE 架构
SPIRE(SPIFFE Runtime Environment)是 SPIFFE 标准的参考实现:
┌─────────────────────────────────────────────────┐
│ SPIRE Server │
│ ┌────────────┐ ┌────────────┐ ┌─────────────┐ │
│ │ CA Manager │ │ Registry │ │ DataStore │ │
│ │ 签发 SVID │ │ 注册项管理 │ │ SQLite/PG │ │
│ └────────────┘ └────────────┘ └─────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ Node Attestation Plugins │ │
│ │ AWS IID │ GCP IIT │ K8s PSAT │ Join Token│ │
│ └────────────────────────────────────────────┘ │
└──────────────────┬──────────────────────────────┘
│ mTLS (Node SVID)
┌──────────────────▼──────────────────────────────┐
│ SPIRE Agent │
│ ┌────────────┐ ┌────────────┐ ┌─────────────┐ │
│ │ Workload │ │ Cache │ │ Workload │ │
│ │ API Server │ │ Manager │ │ Attestor │ │
│ └────────────┘ └────────────┘ └─────────────┘ │
│ ┌────────────────────────────────────────────┐ │
│ │ SDS Server │ │
│ │ (Envoy 集成接口) │ │
│ └────────────────────────────────────────────┘ │
└──────────────────┬──────────────────────────────┘
│ Unix Domain Socket
┌──────────────────▼──────────────────────────────┐
│ Workload (应用) │
│ 通过 Workload API 获取 SVID │
└─────────────────────────────────────────────────┘
20.2 Node Attestation(节点证明)
Node Attestation 验证”这个 Agent 运行在哪个节点上”:
插件 |
平台 |
原理 |
|---|---|---|
aws_iid |
AWS |
使用 EC2 Instance Identity Document |
gcp_iit |
GCP |
使用 GCE Instance Identity Token |
azure_msi |
Azure |
使用 Managed Service Identity |
k8s_psat |
Kubernetes |
使用 Projected ServiceAccount Token |
k8s_sat |
Kubernetes |
使用 ServiceAccount Token(旧版) |
join_token |
通用 |
使用预共享的一次性 Token |
x509pop |
通用 |
使用已有的 X.509 证书 |
# 使用 Join Token 进行节点证明
# 1. Server 端生成 Token
spire-server token generate -spiffeID spiffe://example.org/agent/node1
# Token: aaaabbbb-cccc-dddd-eeee-ffffffffffff
# 2. Agent 端使用 Token 加入
spire-agent run \
-joinToken aaaabbbb-cccc-dddd-eeee-ffffffffffff \
-serverAddress spire-server:8081
20.3 Workload Registration(工作负载注册)
注册项(Registration Entry)定义了”什么工作负载应该获得什么 SPIFFE ID”:
# 注册一个 Kubernetes 工作负载
spire-server entry create \
-spiffeID spiffe://example.org/ns/production/sa/web-server \
-parentID spiffe://example.org/agent/node1 \
-selector k8s:ns:production \
-selector k8s:sa:web-server \
-ttl 3600
# 注册一个 Docker 工作负载
spire-server entry create \
-spiffeID spiffe://example.org/service/api \
-parentID spiffe://example.org/agent/node1 \
-selector docker:label:app:api-server
# 注册一个 Unix 进程
spire-server entry create \
-spiffeID spiffe://example.org/service/database \
-parentID spiffe://example.org/agent/node1 \
-selector unix:uid:1000
# 查看所有注册项
spire-server entry show
# 删除注册项
spire-server entry delete -entryID <entry-id>
选择器(Selector)类型
选择器 |
格式 |
说明 |
|---|---|---|
k8s:ns |
k8s:ns:production |
Kubernetes 命名空间 |
k8s:sa |
k8s:sa:web-server |
Kubernetes ServiceAccount |
k8s:pod-label |
k8s:pod-label:app:web |
Pod 标签 |
docker:label |
docker:label:app:api |
Docker 容器标签 |
unix:uid |
unix:uid:1000 |
Unix 用户 ID |
unix:gid |
unix:gid:1000 |
Unix 组 ID |
unix:path |
unix:path:/usr/bin/app |
可执行文件路径 |
20.4 Workload Attestation(工作负载证明)
当工作负载通过 Workload API 请求 SVID 时,Agent 需要验证”谁在调用”:
工作负载证明流程:
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ 工作负载 │───▶│ SPIRE Agent │───▶│ 工作负载证明 │
│ (进程) │ │ │ │ 插件 │
│ │ │ 1. 接收连接 │ │ │
│ │ │ 2. 获取 PID │ │ 3. 查询进程 │
│ │ │ │ │ 信息 │
│ │ │ │ │ 4. 匹配选择器 │
│ │ │ │◀───│ 5. 返回匹配 │
│ │ │ │ │ 的 SPIFFE ID│
│ │◀───│ 6. 签发 SVID │ │ │
└──────────┘ └──────────────┘ └──────────────┘
20.5 CA Manager
SPIRE Server 内置 CA,也可以对接外部 CA:
CA 类型 |
说明 |
适用场景 |
|---|---|---|
内置 CA |
SPIRE 自己管理根密钥 |
开发/测试、小规模 |
Vault CA |
使用 HashiCorp Vault PKI |
已有 Vault 基础设施 |
AWS PCA |
使用 AWS Private CA |
AWS 环境 |
Disk CA |
从磁盘加载 CA 密钥 |
自定义 CA |
20.6 Kubernetes 部署
# values.yaml (Helm Chart)
global:
spire:
trustDomain: example.org
spire-server:
replicaCount: 3 # 高可用
dataStore:
sql:
databaseType: postgres
connectionString: "postgres://spire:password@postgres:5432/spire"
nodeAttestor:
k8sPsat:
enabled: true
caManager:
default:
upstreamAuthority: {} # 使用内置 CA
spire-agent:
workloadAttestors:
- k8s # Kubernetes 工作负载证明
# 使用 Helm 部署
helm repo add spiffe https://spiffe.github.io/helm-charts-hardened/
helm install spire spiffe/spire \
--namespace spire-system \
--create-namespace \
-f values.yaml
20.7 完整实战:两个服务间 mTLS
目标:Service A ←→ Service B 通过 SPIFFE mTLS 通信
1. 部署 SPIRE Server + Agent
2. 注册两个工作负载
3. 应用通过 Workload API 获取 SVID
4. 使用 SVID 建立 mTLS 连接
注册工作负载
# 注册 Service A
spire-server entry create \
-spiffeID spiffe://example.org/service-a \
-parentID spiffe://example.org/agent/node1 \
-selector k8s:ns:default \
-selector k8s:sa:service-a
# 注册 Service B
spire-server entry create \
-spiffeID spiffe://example.org/service-b \
-parentID spiffe://example.org/agent/node1 \
-selector k8s:ns:default \
-selector k8s:sa:service-b
Python 应用代码
# Service A (客户端)
from pyspiffe.spiffe_id.spiffe_id import SpiffeId
from pyspiffe.workloadapi.default_workload_api_client import DefaultWorkloadApiClient
import ssl
import httpx
SPIRE_AGENT_SOCKET = "unix:///run/spire/sockets/agent.sock"
async def call_service_b():
"""使用 SPIFFE mTLS 调用 Service B"""
client = DefaultWorkloadApiClient(SPIRE_AGENT_SOCKET)
# 获取 X.509 SVID
x509_context = client.fetch_x509_context()
svid = x509_context.default_svid
print(f"My SPIFFE ID: {svid.spiffe_id}")
print(f"Certificate expires: {svid.leaf.not_valid_after}")
# 构建 TLS 配置
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
# 加载自己的证书(客户端证书)
ssl_context.load_cert_chain(
certfile=svid.cert_chain_pem,
keyfile=svid.private_key_pem,
)
# 加载信任的 CA(Trust Bundle)
for bundle in x509_context.x509_bundles:
ssl_context.load_verify_locations(cadata=bundle.x509_authorities_pem)
# 发起 mTLS 请求
async with httpx.AsyncClient(verify=ssl_context) as http_client:
response = await http_client.get("https://service-b:8443/api/data")
return response.json()
20.8 常用命令
# === SPIRE Server ===
spire-server entry create ... # 创建注册项
spire-server entry show # 查看所有注册项
spire-server entry delete -entryID xxx # 删除注册项
spire-server token generate ... # 生成 Join Token
spire-server bundle show # 查看 Trust Bundle
spire-server healthcheck # 健康检查
# === SPIRE Agent ===
spire-agent api fetch x509 # 获取 X.509 SVID
spire-agent api fetch jwt -audience myapp # 获取 JWT SVID
spire-agent healthcheck # 健康检查
20.9 小结
SPIRE 是 SPIFFE 的参考实现,提供完整的工作负载身份管理
Server 负责注册管理和 SVID 签发,Agent 负责工作负载证明和 SVID 分发
Node Attestation 验证节点身份,Workload Attestation 验证进程身份
支持多种平台:Kubernetes、AWS、GCP、Azure、Docker、裸机
通过 Workload API 实现零配置的 SVID 获取和自动轮换
生产部署建议:高可用 Server + PostgreSQL + 外部 CA