第二十二章:WIMSE — 多系统环境中的工作负载身份
“当工作负载跨越多个系统边界时,身份不应该在途中丢失。”
mindmap
root((WIMSE))
背景
IETF 工作组
跨系统身份
与 SPIFFE 互补
核心概念
WIT
Txn-Token
Token Exchange
应用场景
多云
SaaS-to-SaaS
混合云
与现有标准
OAuth 2.0
SPIFFE
OIDC
22.1 WIMSE 是什么
WIMSE(Workload Identity in Multi-System Environments)是 IETF 正在制定的标准,解决跨系统环境中工作负载身份传递的问题。
为什么需要 WIMSE
SPIFFE 解决了”工作负载如何获得身份”的问题,但在复杂的多系统调用链中,还有未解决的问题:
问题场景:跨系统调用链
用户 → Service A → Service B → Service C → Database
(AWS) (GCP) (Azure)
1. Service A 有 AWS 的身份(IAM Role)
2. Service B 有 GCP 的身份(Service Account)
3. Service C 有 Azure 的身份(Managed Identity)
问题:
- Service C 如何知道这个请求最初来自哪个用户?
- Service B 如何向 Service C 证明"我是代表 Service A 调用的"?
- 如何防止 Confused Deputy 攻击?
22.2 核心概念
Workload Identity Token(WIT)
WIT 是基于 JWT 的工作负载身份令牌,标识工作负载自身的身份:
{
"iss": "https://issuer.example.com",
"sub": "spiffe://example.com/service-a",
"aud": "spiffe://example.com/service-b",
"exp": 1709510400,
"iat": 1709506800,
"jti": "unique-token-id",
"cnf": {
"kid": "key-binding-id"
}
}
Transaction Token(Txn-Token)
Txn-Token 在调用链中传递,记录完整的调用上下文:
{
"iss": "https://txn-token-service.example.com",
"iat": 1709506800,
"aud": "https://api.example.com",
"txn": "txn-abc-123",
"sub": {
"format": "oidc_id_token",
"iss": "https://idp.example.com",
"sub": "user-alice"
},
"rctx": {
"req_ip": "192.168.1.100",
"req_method": "POST",
"req_path": "/api/transfer"
},
"purp": "transfer_funds"
}
Txn-Token 在调用链中的传递:
用户 ──▶ Service A ──▶ Service B ──▶ Service C
│ │ │
│ 创建 │ 传递 │ 验证
│ Txn-Token │ Txn-Token │ Txn-Token
│ │ │
▼ ▼ ▼
包含用户身份 包含调用链上下文 知道请求来源
和请求目的 和中间服务身份 可以做授权决策
Token Exchange(RFC 8693)
Token Exchange 允许工作负载将一种 Token 交换为另一种:
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ Service A │───▶│ Token Exchange│───▶│ Service B │
│ (AWS) │ │ Service │ │ (GCP) │
│ │ │ │ │ │
│ 持有: │ │ AWS Token │ │ 需要: │
│ AWS IAM │───▶│ → GCP Token │───▶│ GCP SA │
│ Token │ │ │ │ Token │
└──────────┘ └──────────────┘ └──────────┘
import httpx
async def exchange_token(
subject_token: str,
subject_token_type: str,
target_audience: str,
) -> str:
"""OAuth 2.0 Token Exchange (RFC 8693)"""
async with httpx.AsyncClient() as client:
response = await client.post(
"https://token-exchange.example.com/token",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": subject_token,
"subject_token_type": subject_token_type,
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"audience": target_audience,
}
)
return response.json()["access_token"]
# 将 SPIFFE JWT-SVID 交换为目标系统的 Token
new_token = await exchange_token(
subject_token=spiffe_jwt_svid,
subject_token_type="urn:ietf:params:oauth:token-type:jwt",
target_audience="spiffe://gcp.example.com/service-b",
)
22.3 Confused Deputy 攻击
正常流程:
用户 Alice ──▶ Service A ──▶ Service B
(有权限) (执行操作)
Confused Deputy 攻击:
攻击者 Eve ──▶ Service A ──▶ Service B
(被欺骗) (用 A 的权限执行)
Service A 被"迷惑"了,用自己的身份帮攻击者执行了操作。
Txn-Token 的防御:
攻击者 Eve ──▶ Service A ──▶ Service B
创建 Txn-Token 检查 Txn-Token
记录 Eve 的身份 发现请求者是 Eve
拒绝!❌
22.4 WIMSE 与现有标准的关系
标准 |
解决的问题 |
WIMSE 的关系 |
|---|---|---|
SPIFFE |
工作负载如何获得身份 |
互补:WIMSE 传递 SPIFFE 身份 |
OAuth 2.0 |
委托授权 |
扩展:Token Exchange |
OIDC |
用户身份认证 |
集成:Txn-Token 携带用户身份 |
mTLS |
传输层身份验证 |
补充:应用层身份传递 |
22.5 应用场景
多云环境
AWS 服务 ──(WIT)──▶ Token Exchange ──(WIT)──▶ GCP 服务
spiffe://aws.../a AWS→GCP Token转换 spiffe://gcp.../b
SaaS-to-SaaS
SaaS A ──(Txn-Token)──▶ SaaS B
用户在 A 中触发操作 B 知道请求来自 A 的用户
可以做细粒度授权
22.6 小结
WIMSE 解决跨系统环境中的工作负载身份传递问题
WIT 标识工作负载自身身份,Txn-Token 传递调用链上下文
Token Exchange 实现跨系统的 Token 转换
WIMSE 与 SPIFFE 互补:SPIFFE 提供身份,WIMSE 传递身份
Confused Deputy 攻击是 WIMSE 要解决的核心安全问题
WIMSE 标准仍在 IETF 制定中,但核心概念已经清晰