4、服务网格治理:Envoy与SPIFFE集成、mTLS通信、授权策略
在服务网格架构中,Envoy 作为数据面代理,承担着所有服务间流量的拦截与转发职责。SPIFFE 标准为每个工作负载颁发唯一的身份标识(SPIFFE ID),而 SPIRE 则是该标准的参考实现。本章将深入剖析 Envoy 如何与 SPIRE 集成,实现基于 SPIFFE 身份的 mTLS 通信,并在此基础上构建细粒度的授权策略。
4.1 Envoy与SPIRE的集成架构
Envoy 通过 Secret Discovery Service (SDS) 与 SPIRE Agent 进行集成。SPIRE Agent 负责向 Envoy 动态下发 TLS 证书和私钥,这些证书中嵌入了工作负载的 SPIFFE ID。集成架构分为控制面与数据面两个层面:
- 控制面集成: SPIRE Server 通过节点 attestation 和工作负载 attestation 确认 Pod/容器的身份,并签发 X.509-SVID 证书。SPIRE Agent 通过 Unix Domain Socket 暴露 SDS 接口。
- 数据面集成: Envoy 的 SDS 配置指向 SPIRE Agent 的 socket 路径。Envoy 启动时或证书即将过期时,自动向 SPIRE Agent 请求新的证书和私钥。
config_source 的 api_config_source 必须指向 SPIRE Agent 暴露的 SDS 服务器地址(通常为 unix:///spire-agent/api/sds)。Envoy 无需直接访问 SPIRE Server,所有证书轮换由 SPIRE Agent 透明处理。
4.2 基于SPIFFE的mTLS通信
当 Envoy 获取到包含 SPIFFE ID 的 X.509-SVID 证书后,即可在服务间建立双向 TLS(mTLS)连接。mTLS 通信的核心流程如下:
- 发起连接: 客户端 Envoy 向目标服务发起 TLS 握手,出示自己的 SVID 证书。
- 验证身份: 服务端 Envoy 验证客户端证书的签名链,并提取 SPIFFE ID(例如
spiffe://cluster.local/ns/default/sa/service-a)。 - 双向验证: 服务端 Envoy 也出示自己的 SVID 证书,客户端 Envoy 同样验证服务端身份。
- 加密通信: 握手完成后,所有流量通过 TLS 加密隧道传输。
| 字段 | 说明 | 示例值 |
|---|---|---|
| URI SAN | 证书中的主体标识,携带 SPIFFE ID | spiffe://cluster.local/ns/default/sa/webapp |
| Common Name (CN) | 通常与 SPIFFE ID 保持一致 | webapp.cluster.local |
| 证书有效期 | SPIRE 签发的 SVID 默认 1 小时,可配置 | 3600 秒 |
| 密钥算法 | 推荐 ECDSA P-256 或 RSA 2048+ | ECDSA P-256 |
STRICT,拒绝所有非 mTLS 流量。同时,通过 SPIRE 的 Registration Entry 确保每个工作负载只获得其应有的 SPIFFE ID,防止身份伪造。
4.3 授权策略:从身份到权限
mTLS 仅解决了“你是谁”的问题,而授权策略解决的是“你能做什么”。Envoy 通过 RBAC (Role-Based Access Control) 过滤器实现基于 SPIFFE ID 的细粒度访问控制。授权策略通常包含三个要素:
- 主体(Principal): 发起请求的工作负载的 SPIFFE ID。
- 操作(Action): 允许(ALLOW)或拒绝(DENY)。
- 条件(Condition): 请求路径、方法、Header 等匹配规则。
以下是一个典型的 Envoy RBAC 配置片段,仅允许 service-a 访问 service-b 的 /api/v1/orders 路径:
static_resources:
listeners:
- name: listener_0
filter_chains:
- filters:
- name: envoy.filters.network.rbac
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules:
action: ALLOW
policies:
"allow-service-a":
permissions:
- any: true
principals:
- authenticated:
principal_name:
exact: "spiffe://cluster.local/ns/default/sa/service-a"
conditions:
- source:
header:
name: ":path"
string_match:
prefix: "/api/v1/orders"
STRICT mTLS 和 RBAC 过滤器,形成双重安全防线。
4.4 版本差异校验中的授权策略考量
在服务网格治理回滚护栏场景中,授权策略需要感知不同版本的工作负载。例如,当 Service A v2 回滚到 v1 时,其 SPIFFE ID 可能保持不变(因为 ServiceAccount 相同),但 Envoy 可以通过 额外元数据 或 版本标签 来区分版本。推荐的做法包括:
- 利用 SPIFFE ID 中的版本信息: 在注册 Entry 时,为不同版本的工作负载分配不同的 SPIFFE ID,例如
spiffe://cluster.local/ns/default/sa/service-a/v1和spiffe://cluster.local/ns/default/sa/service-a/v2。 - 结合 Envoy 的 Metadata 匹配: 在 RBAC 策略中,除了匹配 SPIFFE ID,还可以匹配请求中的自定义 Header(如
X-Version: v2),实现版本级访问控制。 - 动态策略更新: 回滚发生时,通过控制面(如 Istio 的 AuthorizationPolicy CRD)自动更新 RBAC 规则,确保旧版本工作负载的权限与新版本一致或受限。
通过 Envoy 与 SPIFFE 的深度集成,服务网格不仅实现了自动化的 mTLS 通信,还构建了基于身份的动态授权体系。这套体系在版本回滚场景中,能够自动感知工作负载身份的变化,并实时调整访问控制策略,为回滚操作提供坚实的安全护栏。