土法炼钢兴趣小组的算法知识备份

【身份与访问控制工程】服务身份:mTLS、SPIFFE/SPIRE 与 Workload Identity

文章导航

分类入口
architecturesecurity
标签入口
#mtls#spiffe#spire#workload-identity#x509#svid#oauth2#jwt-profile#service-mesh#zero-trust

目录

前面的文章全部聚焦于”人的身份”——OIDC、SAML、MFA、Passkey 解决的都是”坐在键盘前的人是谁”。但在一个数百微服务的 K8s 集群中,每个服务之间的调用也需要身份。当 order-service 调用 payment-service 时,后者怎么知道”这个请求的确来自 order-service,而不是某个攻入集群内部的进程在伪造”?

这就是 Workload Identity(工作负载身份)——对软件工作负载(不是人)的身份管理。在零信任架构中(参见本站零信任架构篇),Workload Identity 和 User Identity 同等重要。本文从三个技术层面讨论:传输层(mTLS)、平台层(SPIFFE/SPIRE)、应用层(OAuth 2.0 JWT Profile)。

一、mTLS:传输层的服务身份

1.1 基本原理

普通 TLS(单向 TLS)只验证服务端:客户端确认”我连接的是真的 payment-service”。mTLS(双向 TLS)同时也验证客户端:服务端确认”连接我的是真的 order-service”。

sequenceDiagram
    participant Client as order-service
    participant Server as payment-service

    Client->>Server: 1. ClientHello
    Server->>Client: 2. ServerHello + Server Certificate (cert.payment)
    Client->>Client: 3. 验证 Server Cert (CA 链 + DNS SAN)
    Client->>Server: 4. Client Certificate (cert.order)
    Server->>Server: 5. 验证 Client Cert (CA 链 + SPIFFE ID)
    Server->>Client: 6. TLS 握手完成
    Client->>Server: 7. 加密的应用数据

1.2 证书管理与 X.509 扩展

mTLS 的部署难点在证书生命周期管理——不是”怎么签”(OpenSSL 一行命令),而是:

  1. 签发:谁为新部署的服务签发证书?
  2. 轮换:证书过期前怎么自动换新?
  3. 吊销:服务被下线后,它的旧证书怎么被标记为无效?
  4. 信任域:dev 环境的证书在 prod 环境能用吗?

K8s 生态的 cert-manager(基于 ACME 协议,与 Let’s Encrypt 集成的证书自动管理工具)解决了第 1-2 个问题。对于 mTLS 中的内部证书,cert-manager 可以维护一个内部 CA,为每个 Pod 自动签发短期证书(如 24 小时有效期),并通过 cert-manager-csi-driver 将证书挂载到 Pod 的文件系统或 tmpfs。

X.509 证书的 SAN(Subject Alternative Name)扩展中的 URI 类型是编排系统中最常用的服务身份表达方式。例如:URI:spiffe://cluster.local/ns/payment/sa/payment-sa

1.3 mTLS 的局限性

mTLS 解决的问题:传输层的身份——确认对方有合法证书。

mTLS 不解决的问题: - 证书管发本身:谁是 CA?CA 信任什么? - 身份模型:证书中的身份怎么映射到”这个服务有权访问这个 API”? - 应用层授权:mTLS 通过后,order-service 能不能 POST 到 payment-service 的 /refund 端点?

这就是 SPIFFE 和 OAuth 2.0 Token Exchange 进入讨论的原因。

二、SPIFFE/SPIRE:平台层的身份框架

2.1 SPIFFE ID

SPIFFE(Secure Production Identity Framework for Everyone,CNCF Graduated)定义了一种通用的工作负载身份标识格式——SPIFFE ID:

spiffe://trust-domain/ns/namespace/sa/service-account
spiffe://cluster.prod.example.com/ns/payments/sa/payment-processor

URI 结构: - spiffe:// 固定 scheme - trust-domain:信任域——通常对应一个 K8s 集群或一个组织边界 - /ns/{namespace}/sa/{service-account}:K8s 工作负载的典型路径。也可以是 /node/{hostname} 或自定义路径

2.2 SPIRE:SPIFFE 的参考实现

SPIRE(SPIFFE Runtime Environment)是 SPIFFE 的 CNCF 参考实现,负责 SPIFFE ID 的发放和验证。

SPIRE 的核心组件:

flowchart TD
    SPIRE-Server["SPIRE Server<br/>(集群级别)"]
    SPIRE-Agent1["SPIRE Agent<br/>(Node 1)"]
    SPIRE-Agent2["SPIRE Agent<br/>(Node 2)"]

    Workload1["Pod: payment-service<br/>SA: payment-sa"]
    Workload2["Pod: order-service<br/>SA: order-sa"]

    SPIRE-Agent1 --> SPIRE-Server
    SPIRE-Agent2 --> SPIRE-Server

    Workload1 -->|"Workload API (Unix socket)"| SPIRE-Agent1
    Workload2 -->|"Workload API (Unix socket)"| SPIRE-Agent2

    SPIRE-Agent1 -->|"Node Attestation"| SPIRE-Server
    SPIRE-Agent2 -->|"Node Attestation"| SPIRE-Server
    Workload1 -.->|"mTLS with SVID"| Workload2

关键概念:

2.3 SPIRE 与 Istio/Service Mesh 的关系

SPIRE 和 Istio 不是竞品,是互补的:

Istio 可以配置为使用 SPIRE 作为其 CA,而不是使用 Istio 自带的内置 CA。这样 SPIRE 负责”这个 workload 是谁”,Istio 负责”用这个身份的证书做 mTLS 和鉴权”。

三、OAuth 2.0:应用层的服务身份

mTLS + SPIFFE 解决了传输层和平台层的身份。但很多场景中,服务需要”应用层”的身份令牌——不带 TLS 层的 OAuth 2.0 Access Token,用于调用 REST API 时的 Bearer 认证。

3.1 Client Credentials Grant

最简单的服务间 OAuth 模式:服务作为 OAuth 客户端,用 client_id + client_secret 请求 Access Token。

POST /token
Authorization: Basic base64(client_id:client_secret)
grant_type=client_credentials&scope=payment:write

→ { "access_token": "eyJhbG...", "token_type": "Bearer", "expires_in": 3600 }

Client Credentials Grant 的问题:

3.2 JWT Profile for OAuth 2.0(RFC 7523)

更好的方案是:服务用它已有的 SVID(SPIFFE 证书或 JWT)来向 OP 换取 OAuth Access Token。这称为 JWT Profile for OAuth 2.0(RFC 7523)。SPIRE 可以生成 JWT-SVID,这个 JWT 本身就是 RFC 7523 格式的 assertion:

POST /token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=eyJhbG...jwt_svid...

OP 验证 JWT-SVID:
  - 签名(用 SPIRE 信任域的 JWKS)
  - issuer (spiffe://cluster.local)
  - subject (spiffe://cluster.local/ns/order/sa/order-sa)
  - audience (OP 的 token endpoint)
  - 有效期

→ { "access_token": "eyJhbG...", "token_type": "Bearer" }

这种方式把平台身份(SPIFFE ID)和 OAuth 令牌链在了一起——Access Token 中可以编码对应的 SPIFFE ID,使得资源服务器能追溯到”调用方到底是哪个 K8s workload”。

四、三种层次的选型

层次 技术 粒度 部署复杂度 身份信任根
传输层 mTLS 连接 高(需要 CA 和证书管发) TLS 证书的 CA 链
平台层 SPIFFE/SPIRE 工作负载(Pod/进程) 中-高(需要部署 SPIRE) 节点证明(云平台/TPM)
应用层 OAuth 2.0 Client Credentials / JWT Profile 应用逻辑身份 低-中 OP 的客户端 secret 或 SPIFFE SVID

工程选择不是一个”选哪个”的问题——三者在零信任架构中是同时需要的:

  1. mTLS 保证传输加密和连接级别的相互认证。
  2. SPIFFE/SPIRE 提供平台级别的、可审计的、自动化的身份发行。
  3. OAuth 2.0 Token Exchange 将平台身份转化为应用可用的 Bearer Token,方便在 HTTP API 中传递。

对于没有 K8s 或 Service Mesh 的小规模部署,Client Credentials Grant + HashiCorp Vault 管理 secret 是务实的起点。


上一篇风险感知认证:设备信任、异常登录与挑战升级 下一篇RBAC、ABAC、ReBAC:权限模型怎么选

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-06-12 · architecture / security

零信任安全架构深度系列

零信任是 IAM 的自然延伸——当身份变成新边界,VPN 的'拨入即信任'模型必须被'永不信任、始终验证'取代。本系列从 NIST SP 800-207 规范、Google BeyondCorp 六篇论文、SPIFFE/SPIRE 联邦到微分段、持续验证、ZTNA 和零信任迁移的工程策略,系统拆解零信任的每一种组件和每一步实施。

2026-06-13 · architecture / security

【身份与访问控制工程】IAM 全景:为什么这是高价值赛道

从 2020 年 SolarWinds 到 2024 年 Okta 支持系统泄露,身份基础设施的安全失败反复证明一件事:IAM 不是 IT 支撑系统,而是安全架构的承重墙。本文建立现代 IAM 的全景地图——从认证协议、令牌体系、权限模型到身份治理与平台选型,给出 5 个贯穿全系列的核心问题。


By .