istio.io/content_zh/docs/concepts/security/mutual-tls/index.md

8.0 KiB
Raw Blame History

title description keywords weight
双向 TLS 认证 描述 Istio 的双向 TLS 认证架构,这一功能在服务之间提供了强认证以及加密通讯的能力。
security
mutual-tls
10

Istio 希望在不变更服务代码的情况下增强微服务自身及其通信的安全性,它负责:

  • 为每个服务提供可靠的、代表其角色的身份认证,以实现跨集群和云的互通性

  • 加密服务间通信和终端用户到服务的通信

  • 提供密钥管理系统来自动执行密钥和证书的生成、分发、轮换和撤销

架构

下图展示 Istio 安全相关的架构,其中包括三个主要组件:认证、密钥管理和通信安全。服务 frontend 使用的 Service account 是 frontend-teambackend 服务的 Service account 是 backend-teamIstio 在这两个服务之间的通信过程中进行了加密。不论服务是运行在 Kubernetes 的容器之中,还是运行在虚拟机/裸机上,都能获得 Istio 的支持。

{{< image width="80%" ratio="56.25%" link="/docs/concepts/security/auth.svg" alt="构成 Istio 认证模型的组件" caption="Istio 安全架构" >}}

如图所示Istio 使用 Volume 加载 Secret用这样的方式完成从 Citadel 到 Kubernetes 容器的证书以及密钥的分发。对于在虚拟机或裸机上运行的服务,需要在每个虚拟机和裸机上运行节点代理。它在本地生成私钥和 CSR证书签名请求将 CSR 发送给 Citadel 进行签名,并将生成的证书与私钥一起交给 Envoy。

组件

身份

Istio 使用 Kubernetes service accounts 来识别谁在运行服务:

  • Istio 中的 Service account格式为 spiffe://<domain>/ns/<namespace>/sa/<serviceaccount>

    • domain 目前是 cluster.local ,我们将很快支持域的定制化。
    • namespace 是 Kubernetes service account 所在的命名空间。
    • serviceaccount 是Kubernetes service account 的名称。
  • Service account 是工作负载运行的身份(或角色),表示该工作负载的权限。对于需要强大安全性的系统,工作负载的权限不应由随机字符串(如服务名称,标签等)或部署的二进制文件来标识。

    • 例如假设有一个从多租户数据库中提取数据的工作负载。Alice 和 Bob 都能运行这个工作负载,从中获取数据,但是两个用户最终得到的数据是不同的。
  • Service account 能够灵活的识别机器、用户、工作负载或一组工作负载(不同的工作负载可以使用同一 Service account 运行),从而实现强大的安全策略。

  • Service account 在工作负载的整个生命周期中不会发生变化。

  • 结合域名的约束,能保证 Service account 的唯一性。

通信安全

Istio 中,客户端和服务端的 Envoy 形成通信隧道,服务间的的通信就是通过这些隧道完成的。端到端通信通过以下方式加密:

  • 服务与 Envoy 之间的本地 TCP 连接

  • 代理之间的双向 TLS 连接

  • 安全命名:在握手过程中,客户端 Envoy 检查服务器端证书提供的 Service account 是否允许运行目标服务

密钥管理

Istio 从 0.2 版本开始支持运行于 Kubernetes、虚拟机以及裸机之上的服务。对于每个场景会使用不同的密钥配置机制。

对于运行在 Kubernetes 集群中的服务,

每个集群的 Citadel证书颁发机构

负责自动化执行密钥和证书管理流程。

它主要执行四个关键操作:

  • 为每个 Service account 生成一个 SPIFFE 密钥和证书

  • 根据 Service account 将密钥和证书分发给每个 Pod

  • 定期轮换密钥和证书

  • 必要时撤销特定的密钥和证书对

对于运行在虚拟机或裸机上的服务,上述四个操作会由 Citadel 和节点代理协作完成。

工作流

Istio 安全工作流由部署和运行两阶段组成。Kubernetes 和虚拟机/裸机两种情况下的部署阶段是不一致的,因此我们需要分别讨论;然而一旦证书和密钥部署完成,运行阶段就是一致的了。这里主要讨论这一流程。

Kubernetes 的部署阶段

  1. Citadel 观察 Kubernetes API Server为每个现有和新的 Service account 创建一个 SPIFFE 密钥和证书对,并将其发送到 API Server。

  2. 当创建 Pod 时API Server 会根据 Service account 使用 Kubernetes secrets 来挂载密钥和证书对。

  3. Pilot 使用适当的密钥和证书以及安全命名信息生成配置,该信息定义各个 Service account 的可运行服务,并将其传递给 Envoy。

虚拟机/裸机的部署阶段

  1. Citadel 创建 gRPC 服务来处理 CSR 请求。

  2. 节点代理创建私钥和 CSR发送 CSR 到 Citadel 进行签署。

  3. Citadel 验证 CSR 中携带的证书,并签署 CSR 以生成证书。

  4. 节点代理将从 Citadel 接收到的证书和私钥发送给 Envoy。

  5. 上述 CSR 流程定期重复,从而完成证书的轮转过程。

运行时阶段

  1. 来自客户端服务的出站流量被重新路由到它本地的 Envoy。

  2. 客户端 Envoy 与服务器端 Envoy 开始进行双向 TLS 的握手。在握手期间,它还进行安全的命名检查,以验证服务器证书中显示的服务帐户是否可以运行这一服务。

  3. mTLS 连接成功以后,流量将转发到服务器端 Envoy然后通过本地 TCP 连接转发到服务器服务。

最佳实践

在本节中,我们提供了一些部署指南,然后讨论了一个现实世界的场景。

部署指南

  • 如果有多个服务运维人员(也称为 SRE 在集群中部署不同的服务(通常在中型或大型集群中),我们建议为每个 SRE 团队创建一个单独的 namespace,来进行访问隔离。例如,您可以为 team1 创建一个 "team1-ns" 命名空间,为 team2 创建 "team2-ns" 命名空间,这样两个团队就无法访问对方的服务。

  • 如果 Citadel 受到威胁,则可能会在集群中暴露它管理的所有密钥和证书。我们强烈建议在专门的只有集群管理员才能访问的命名空间例如istio-citadel-ns上运行 Citadel。

示例

我们设想一个三层的应用程序,其中有三个服务:照片前端,照片后端和数据存储。照片前端和照片后端服务由照片 SRE 团队管理,而数据存储服务由数据存储 SRE 团队管理。照片前端可以访问照片后端,照片后端可以访问数据存储。但是,照片前端无法访问数据存储。

在这种情况下,集群管理员创建 3 个命名空间istio-citadel-ns、photo-ns 以及 datastore-ns。管理员可以访问所有命名空间每个团队只能访问自己的命名空间。照片 SRE 团队创建了两个 Service account在命名空间 photo-ns 中运行照片前端和照片后端。数据存储 SRE 团队创建一个 Service account 以在命名空间 datastore-ns 中运行数据存储服务。此外,我们需要在 Istio Mixer 中强制执行服务访问控制,以使照片前端无法访问数据存储。

在此设置中Citadel 能够为所有命名空间提供密钥和证书管理,并隔离彼此的微服务部署。

未来工作展望

  • 跨集群的服务间认证

  • 强大的认证机制ABAC, RBAC等

  • 支持单一服务的认证启用

  • 为 Istio 组件Mixer, Pilot提供安全加固

  • 使用 JWT/OAuth2/OpenID_Connect 提供终端用户和服务之间的认证

  • 支持 GCP Service account

  • 为服务和 Envoy 之间的本地通信提供 Unix 套接字支持

  • 中间代理支持

  • 可插拔密钥管理组件