概述
将单一的应用程序分解成微服务有很多好处,包括更好的灵活性、可伸缩性以及服务复用的能力。但是,微服务也有特殊的安全需求:
- 为了抵御中间人攻击,需要流量加密
- 为了提供灵活的服务访问控制,需要双向TLS和细粒的访问策略。
- 要审核谁在什么时候做了什么,需要审计工作
Istio Security 尝试提供全面的安全解决方案来解决所有这些问题。Istio 安全性可以缓解针对您的数据、端点、通信和平台的内部和外部威胁。
Isito安全功能提供了强大的身份和策略,透明的TLS加密以及用于保护您的服务和数据的身份验证,授权和审计(AAA)工具。它的安全目标是:
- 默认安全:应用程序代码和基础结构无需更改
- 深度防御:与现有安全系统集成,提供多层防御
- 零信任网络:在不受信任的网络上构建安全解决方案
Istio的 citadel用加载Secret卷的方式在Kubernetes 容器中完成证书和密钥的分发。如果服务运行在虚拟机或物理机上,则会使用运行在本地的Node agent ,它负责本地私钥和CSR(证书签发申请),把CSR发送给Cidadel进行签署,并把生成的证书和私钥发给Envoy。
高级架构
Istio中的安全性涉及多个组件:
- Citadel用于密钥和证书管理
- Sidecar和代理实现客户端和服务器之间的安全通信
- Pilot将授权信息和安全命名信息发送给代理
- Mixer管理授权和审计
Istio身份
身份是任何安全基础架构的基本概念。在服务到服务通信开始时,双方必须与其身份信息交换凭证以用于相互认证目的。在客户端,根据安全命名信息检查服务器标示,以查看它是否是该服务的授权运行程序,在服务器端,服务器可以根据授权策略确定客户端可以访问那些资源,审核谁在什么时间访问了什么。比如,服务端可以允许客户端已经付费了的请求,未支付的禁止客户端访问。
在 Istio 身份模型中,Istio 使用服务标示来确定服务的身份。这为表示用户、单个服务和一组服务提供了极大的灵活性和粒度。在没有此身份平台上,Istio可以使用分组的其他身份,比如服务名称,来对实例进行分组。
不通平台的服务标示:
- Kubernetes: Kubernetes 服务帐户
- GKE/GCE: 可以使用 GCP 服务帐户
- GCP: GCP 服务帐户
- AWS: AWS IAM 用户/角色 帐户
- On-premises (非 Kubernetes): 用户帐户、自定义服务帐户、服务名称、Istio 服务帐户或 GCP 服务帐户。
自定义服务帐户引用现有服务帐户,就像客户的身份目录管理的身份一样。
Istio安全与SPIFFE
SPIFFE提供了一个框架规范,该框架可以跨异构环境引导和向服务发布身份。
Istio和SPIFFE共享相同的身份文件:SVID(SPIFFE可验证身份证件)。例如,在kubernetes中,X.509证书的URI字段格式为:spiffe://<domain>/ns/<namespace>/sa/<serviceaccount>。这使Istio服务能够建立与接受与其他SPIFFE兼容系统的连接。
Istio安全性和SPIRE的实现,在PKI实现细节上有所不同。Istio提供了更加全面的安全解决方案,包括身份验证、授权和审计。
PKI
Istio PKI 建立在Istio Citadel之上,可以为每个工作负载安全地提供强大的工作负载标识。Istio使用X.509 证书来携带SPIFFE格式的身份。PKI 还可以大规模自动化密钥和证书轮换。
Istio支持Kubernetes pod 和本地计算机上运行的服务。目前,每个方案使用不同的证书秘钥配置机制。
- Kubernetes方案
Citadel监视 Kubernetes apiserver,为每个现有和新的服务帐户创建 SPIFFE 证书和密钥对。Citadel 将证书和密钥对存储为 Kubernetes secret。
创建 pod 时,Kubernetes 会根据其服务帐户通过 Kubernetes secret volume 将证书和密钥对挂载到 pod。
Citadel 监视每个证书的生命周期,并通过重写 Kubernetes 秘密自动轮换证书。
Pilot 生成安全命名信息,该信息定义了哪些 Service Account 可以运行哪些服务。Pilot 然后将安全命名信息传递给 envoy sidecar。
- 本地机器运行方案
- Citadel 创建 gRPC 服务来接受CSR(证书签名请求)
- 节点代理生成私钥和 CSR,并将 CSR 及其凭据发送给 Citadel 进行签名。
- Citadel 验证 CSR 承载的凭证,并签署 CSR 以生成证书。
- 节点代理将从 Citadel 接收的证书和私钥发送给 Envoy。
- 上述 CSR 过程会定期重复进行证书和密钥轮换。
- Kubernetes 中的代理节点
Istio 提供了在 Kubernetes 中使用节点代理进行证书和密钥分配的选项,此外本地计算机的标识提供流程是相同的。如下图所示,
流程如下:
- Citadel 创建一个 gRPC 服务来接受 CSR 请求。
- Envoy 通过 Envoy secret 发现服务(SDS)API 发送证书和密钥请求。
- 收到 SDS 请求后,节点代理会创建私钥和 CSR,并将 CSR 及其凭据发送给 Citadel 进行签名。
- Citadel 验证 CSR 中携带的凭证,并签署 CSR 以生成证书。
- 节点代理通过 Envoy SDS API 将从 Citadel 接收的证书和私钥发送给 Envoy。
- 上述 CSR 过程会定期重复进行证书和密钥轮换。
实践建议
不同的团队创建不同的Kubernetes 命名空间。
在专用命名空间中运行 Citadel,以便仅限管理员访问群集,防止入侵。
认证
Istio提供两种种类型的身份验证。
传输身份验证,也称为服务到服务身份验证。Istio提供双向TLS作为传输身份验证的完整堆栈解决方案,无需更改服务代码。
- 为每个服务提供强大的身份,表示其角色,以实现跨群集和云的互操作性。
- 保护服务到服务通信和最终用户到服务通信。
- 提供密钥管理系统,以自动执行密钥和证书生成,分发和轮换。
来源身份认证,也称为最终用户身份验证,即客户端到服务端的身份认证。Istio通过JWT(Json Web Token)、Auth或自定义身份验证来简化开发人员体验,并且轻松实现请求级别的身份验证。
在这两种情况下,Istio 都通过自定义 Kubernetes API 将身份认证策略储在 Istio 配置存储中。Pilot会在适当的时候为每个代理保持最新状态以及密钥。此外,Istio 支持在宽容模式下进行身份验证,以帮助您了解策略更改在其生效之前如何影响您的安全状态。
- 双向TLS认证
客户端和服务端通信都需要通过Envoy代理进行,对于客户端调用服务端,注意此处的客户端也可能是一个服务,比如服务A调用服务B,服务A相当于客户端,遵循以下步骤:
- Istio 将出站流量从客户端重新路由到客户端的本地sidecar Envoy
- 客户端的Envoy和服务端的Envoy建立了一个双向的 TLS 连接,Istio 将流量从客户端 Envoy 转发到服务器端 Envoy。
- 授权后,服务器端 Envoy 通过本地 TCP 连接将流量转发到服务器服务。
- 宽容模式
Istio 双向 TLS 具有一个宽容模式(permissive mode),即不需要授权和认证,允许 service 同时接受纯文本流量和双向 TLS 流量。该功能有利于测试,主要用于非Istio客户端和非 Istio 服务端间的通信,避免因权限而导致无法连接的情况。
举个实际场景,启用宽容模式后,服务同时接受纯文本和双向 TLS 流量。这个模式为入门提供了极大的灵活性。服务中安装的 Istio sidecar 立即接受双向 TLS 流量而不会打断现有的纯文本流量。因此,运维人员可以逐步安装和配置客户端 Istio sidecars 发送双向 TLS 流量。一旦客户端配置完成,运维人员便可以将服务端配置为仅 TLS 模式。
- 安全命名
安全命名信息包含从编码在证书中的服务器标识到被发现服务或DNS引用的服务名称N到N的映射。从身份 A 到服务名称 B 的映射意味着“允许 A 并授权其运行服务 B”。Pilot监视Kubernetes apiserver,生成安全的命名信息,并将其安全地分发给 sidecar Envoy。例如:
假设运行服务 datastore 的合法服务器仅使用 infra-team 标识。恶意用户拥有 test-team 身份的证书和密钥。恶意用户打算模拟服务以检查从客户端发送的数据。恶意用户使用证书和 test-team 身份的密钥部署伪造服务器。假设恶意用户成功攻击了发现服务或 DNS,以将 datastore 服务名称映射到伪造服务器。
当客户端调用 datastore 服务时,它从服务器的证书中提取 test-team 标识,并检查是否允许 test-team 运行带有安全命名信息的 datastore。客户端检测到 test-team 不允许运行 datastore 服务,并且验证失败。
- 认证架构
您可以使用身份认证策略为在 Istio 网格中接收请求的服务指定身份验证要求。Istio使用者采用yaml文件来指定策略。部署后,策略将保存在 Istio Config Store。 Pilot、Istio 控制器监视配置存储。一有任何的策略变更,Pilot 会将新策略转换为适当的配置,告知 Envoy sidecar 代理如何执行所需的身份验证机制。Pilot 可以获取公钥并将其附加到 JWT 验证配置。或者,Pilot 提供 Istio 系统管理的密钥和证书的路径,并将它们挂载到应用程序 pod 以进行双向 TLS。Istio 异步发送配置到目标端点。代理收到配置后,新的身份验证要求会立即生效。
发送请求的客户端服务负责遵循必要的身份验证机制。对于源身份验证(JWT),应用程序负责获取 JWT 凭据并将其附加到请求。对于双向 TLS,Istio 提供目标规则。运维人员可以使用目标规则来指示客户端代理使用 TLS 与服务器端预期的证书进行初始连接。
Istio 将两种类型的身份验证以及凭证中的其他声明(如果适用)输出到下一层:授权。此外,运维人员可以指定将传输或原始身份验证中的哪个身份作为委托人使用。
授权
Istio 的授权功能也称为基于角色的访问控制(RBAC)-为Istio服务提供命名空间级别、服务级别和方法级别的访问控制。它的特点:
- 基于角色的语义,简单易用。
- 服务间和最终用户对服务的授权
- 通过自定义属性支持灵活性,例如条件、角色和角色绑定。
- 高性能,因为 Istio 授权是在 Envoy 本地强制执行的。
- 高兼容性,原生支持 HTTP、HTTPS 和 HTTP2,以及任意普通 TCP 协议。
授权架构
上图显示了基本的 Istio 授权架构。运维人员使用 yaml 文件指定 Istio 授权策略。部署后,Istio 将策略保存在 Istio Config Store 中。
Pilot 监督 Istio 授权策略的变更。如果发现任何更改,它将获取更新的授权策略。 Pilot 将 Istio 授权策略分发给与服务实例位于同一位置的 Envoy 代理。
每个 Envoy 代理都运行一个授权引擎,该引擎在运行时授权请求。当请求到达代理时,授权引擎根据当前授权策略评估请求上下文,并返回授权结果 ALLOW 或 DENY。
启用授权
您可以使用 RbacConfig 对象启用 Istio Authorization。RbacConfig 对象是Istio中的一种实例,其固定名称值为 default。你只能在Istio网络中使用一个RbacConfig实例。与其他 Istio 配置对象一样,RbacConfig 被定义为Kubernetes CustomResourceDefinition (CRD) 对象。
在 RbacConfig 对象中,可以指定 mode 值,它可以是:
ON:为所有的Istio服务启动Istio授权
OFF:禁用Istio授权
ON_WITH_INCLUSION:仅对包含字段中指定的服务和命名空间启用 Istio 授权。
ON_WITH_EXCLUSION:除了排除字段中指定的服务和命名空间外,网格中的所有服务都启用了 Istio 授权。
例如:在以下示例中,为 default 命名空间启用了 Istio 授权。
apiVersion: "rbac.istio.io/v1alpha1"
kind: RbacConfig
metadata:
name: default
namespace: istio-system
spec:
mode: 'ON_WITH_INCLUSION'
inclusion:
namespaces: ["default"]