凡是产生链接关系,就一定带来安全问题,人类社会如此,服务网格世界,亦是如此。html
今天,咱们就来谈谈Istio第二主打功能---保护服务。面试
那么,便引出3个问题:api
l Istio凭什么保护服务?浏览器
l Istio具体如何保护服务?安全
l 如何告诉Istio发挥保护能力?网络
将单体应用程序分解为一个个服务,为大型软件系统的开发和维护带来了诸多好处,好比更好的灵活性、可伸缩性和可复用性。但这也带来了一些安全问题:架构
l 为了抵御中间人攻击,须要对流量进行加密运维
l 为了提供灵活的服务访问控制,须要 mTLS(双向的安全传输层协议)和细粒度的访问策略工具
l 要审计谁在何时作了什么,须要审计工具性能
Istio 尝试提供全面的安全解决方案来解决这3个问题。
如上图所示,
Istio 安全的三大目标是:
l 默认安全(Security by default):应用程序代码和基础结构,无需更改。
l 深度防护(Defense in depth):与现有安全系统集成,提供多层防护。
l 零信任网络(Zero-trust network):在不受信任的网络上,构建安全解决方案。
为了实现这3个目标,Istio 安全功能提供了4大守护系统:
l 强大的身份(Identity)系统
l 健壮的策略(Policy)系统
l 认证,受权和审计(AAA:Authentication,Authorization,Accounting)系统,用于保护服务和数据
l 透明的 TLS 加密(Encryption)系统。
就保护对象而言,Istio 安全系统能够抵御来自内部或外部的威胁,这些威胁主要针对服务网格内的端点(Endpoints),通讯(Communication),平台(Platform)和数据(Data)。
在安全方面,Istio具有3个远大的目标,配备了4大守护系统,那么它究竟是经过怎样的架构实现这个目标的呢,又经过什么样的安全基础设施,和kubernetes配合呢?
如上图,与Istio的4大守护系统相对应,Istio 中涉及安全的组件有:
l Pilot :将受权策略和安全命名信息分发给代理
l Proxy :实现客户端和服务端之间的安全通讯
l Citadel :用于密钥和证书管理
l Mixer :管理受权和审计
因而可知,Pilot不只负责流量规则和策略的分发,还负责安全相关策略的下发,有点像皇上的贴身太监,负责宣读圣旨;Proxy有点像各州属的州官,负责奉天承运;Citadel有点像玉玺和虎符,负责鉴真去假;Mixer有点像三省六部,负责受权审计。
身份(Identity)是几乎全部安全基础架构的基本概念。在服务和服务的通讯开始前,双方必须用其身份信息交换凭证,以达到相互认证的目的。在客户端,根据安全命名(secure naming)信息,检查服务端的标识,以查看它是不是该服务的受权运行程序;在服务端,服务端能够根据受权策略(authorization policies)信息,肯定客户端能够访问哪些数据,审计其在什么时间访问了什么,拒绝未受权客户端的访问。
在 Istio 身份模型中,Istio 使用一流的服务标识来肯定服务的身份。这为表示人类用户,单个服务或一组服务提供了极大的灵活性和粒度。在没有此类身份的平台上,Istio 可使用能够对服务实例进行分组的其余身份,例如服务名称。
不一样平台上的 Istio 服务标识:
l Kubernetes: Kubernetes 服务账户
l GKE/GCE: 可使用 GCP 服务账户
l AWS: AWS IAM 用户/角色 账户
l On-premises (non-Kubernetes): 用户账户,自定义服务账户,服务名称,istio 服务账户或 GCP 服务账户。
作个类比,京东和天猫都有本身的一套很是成熟的服务帐户系统,淘宝只须要复用天猫的帐户系统便可,无需从新开发一套,这样咱们就能够用天猫的帐号,直接登陆淘宝。而Istio也更倾向于复用业界一流的服务帐户系统,如Kubernetes和AWS的,但也能够自定义服务帐户,并按需复用Kubernetes的帐户系统。
Istio PKI(Public Key Infrastructure)创建在 Istio Citadel 之上,可为每一个工做负载提供安全且强大的工做负载标识。Istio 使用 X.509 证书来携带 SPIFFE 格式的身份信息。PKI 还能够大规模自动化地进行密钥和证书轮换。
Istio 支持在 Kubernetes pod 和本地计算机上运行的服务。目前,Istio为每一个方案使用不一样的证书密钥配置机制,下面试举例Kubernetes方案的配置过程:
如上一章节所言,Istio基于控制面组件,引入了一流的服务帐户系统,结合强大的PKI,实现了对服务网格的安全守护。同时,Istio也开放了接口,让咱们能够进行精细化的配置,全方位知足咱们对服务的安全需求。
服务安全,老是离不开两个具体过程:认证(Authentication)和鉴权(Authorization)。Istio经过Policy和MeshPolicy文件,实现对认证相关功能的定义;经过RbacConfig、ServiceRole和ServiceRoleBinding文件,实现对鉴权相关功能的启用和定义。
让咱们举个几个通俗的例子来区分认证和鉴权:
进火车站须要提供身份证和火车票,身份证能够证实你就是你,这是认证;火车票能够证实你有权上那趟火车,这是受权。
又例如,你要访问本身淘宝的购物车,须要先登陆,这是认证。你要访问朋友的购物车,就须要他的容许,这是受权。
再例如,有经验的朋友能发现浏览器常常会面对两个错误码:401和403。一般而言,401就是未登陆的意思,须要认证;403就是禁止访问的意思,须要受权。
Istio 提供两种类型的身份认证:
l 传输身份认证,也称为服务到服务身份认证:对直连客户端进行验证。Istio 提供双向TLS做为传输身份认证的全栈解决方案。咱们能够轻松启用此功能,而无需更改服务代码。这个解决方案:
l 为每一个服务提供强大的身份认定,以实现跨群集和跨云的互操做性。
l 保护服务到服务通讯和最终用户到服务通讯。
l 提供密钥管理系统,以自动执行密钥和证书生成,分发和轮换。
l 来源身份认证,也称为终端用户身份认证:对来自终端用户或设备的原始客户端请求进行验证。Istio 经过 JSON Web Token(JWT)、Auth0、Firebase Auth、Google Auth 和自定义身份认证来简化开发者的工做,使之轻松实现请求级别的身份认证。
在这两种状况下,Istio 都经过自定义 Kubernetes API 将身份认证策略存储在 Istio 配置存储(Istio config store)中。Pilot会在适当的时候进行同步,为每一个Proxy更新其最新状态以及密钥。此外,Istio 支持在许可模式下进行身份认证,以帮助咱们理解策略变动先后,服务的安全状态是如何变化的。
咱们可使用身份认证策略,为 Istio 网格中接收请求的服务指定身份认证要求。咱们使用 .yaml 文件来配置策略,策略将保存在 Istio 配置存储中。在任何策略变动后,Pilot 会将新策略转换为适当的配置,下发给Envoy,告知其如何执行所需的身份认证机制。Pilot 能够获取公钥并将其附加到 JWT 进行配置验证。或者,Pilot 提供 Istio 系统管理的密钥和证书的路径,并将它们安装到负载 Pod 中,以进行双向 TLS。
本文屡次提到双向TLS认证,让咱们理解一下其在Istio里的实现。Istio 经过客户端和服务端各自配备的Envoy进行通讯,也就是说,客户端和服务端的流量,是被各自的Envoy接管了的。对于客户端调用服务端,遵循的步骤是:
和其余的 Istio 配置同样,能够用 .yaml 文件的形式来编写认证策略,而后使用 Istioctl 二进制工具进行部署。以下图的配置,经过配置Policy文件,对reviews服务进行了传输身份认证的配置,要求其必须使用双向TLS作认证。
apiVersion: "authentication.Istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "reviews"
spec:
targets:
- name: reviews
peers:
- mtls: {}
Istio 的受权功能,也称为基于角色的访问控制(RBAC),为 Istio 服务网格中的服务提供命名空间级别,服务级别和方法级别的访问控制。它的特色是:
l 基于角色的语义,简单易用。
l 包含服务到服务和终端用户到服务两种受权模式。
l 经过自定义属性灵活定制受权策略,例如条件,角色和角色绑定。
l 高性能,由于 Istio 受权功能是在 Envoy 里执行的。
上图显示了基本的 Istio 受权架构。和认证的生效过程同样,运维人员使用.yaml文件指定 Istio 受权策略。部署后,Istio 将策略保存在Istio Config Store中。Pilot 会一直监视 Istio 受权策略的变动,若是发现任何更改,它将获取更新的受权策略,并将 Istio 受权策略分发给与服务实例位于同一 pod 内的 Envoy 代理。
每一个 Envoy 代理都运行一个受权引擎,该引擎在运行时受权请求。当请求到达代理时,受权引擎根据当前受权策略评估请求上下文,并返回受权结果ALLOW或DENY。
咱们可使用 RbacConfig 启用受权策略,并使用ServiceRole和ServiceRoleBinding配置受权策略。
RbacConfig是一个网格维度的单例,其固定名称值为default,也就是说咱们只能在网格中配置一个RbacConfig实例。与其余 Istio 配置对象同样,RbacConfig被定义为Kubernetes CustomResourceDefinition (CRD)对象。
在RbacConfig中,运算符能够指定mode值,它能够是:
l OFF:禁用 Istio 受权。
l ON:为网格中的全部服务启用了 Istio 受权。
l ON_WITH_INCLUSION:仅对包含字段中指定的服务和命名空间启用 Istio 受权。
l 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"]
针对服务和命名空间启用受权后,咱们还须要配置具体的受权策略,这经过配置ServiceRole和ServiceRoleBinding实现。与其余 Istio 配置对象同样,它们一样被定义为CRD对象。
ServiceRole定义了一组访问服务的权限。ServiceRoleBinding向特定对象授予 ServiceRole,例如用户,组或服务。
ServiceRole 和 ServiceRoleBinding 组合规定了: 容许谁在哪些条件下作什么,具体而言:
l 谁指的是 ServiceRoleBinding 中的 subject 部分。
l 作什么指的是 ServiceRole 中的 rule 部分。
l 哪些条件指的是咱们能够在 ServiceRole 或 ServiceRoleBinding 中使用Istio Attributes指定的 condition 部分。
让咱们再举一个简单的例子,以下图,ServiceRole和 ServiceRoleBinding的配置规定:将全部用户(user=“*”)绑定为(products-viewer)角色,这个角色能够对products这个服务发起GET或HEAD请求,可是其限制条件是请求头必须包含version,且值为v1或v2。
apiVersion: "rbac.Istio.io/v1alpha1"
kind: ServiceRole
metadata:
name: products-viewer
namespace: default
spec:
rules:
- services: ["products"]
methods: ["GET", "HEAD"]
constraints:
- key: request.headers[version]
values: ["v1", "v2"]
---
apiVersion: "rbac.Istio.io/v1alpha1"
kind: ServiceRoleBinding
metadata:
name: binding-products-allusers
namespace: default
spec:
subjects:
- user: "*"
roleRef:
kind: ServiceRole
name: "products-viewer"
至此,咱们作个简单的总结:单体应用程序拆分红成千上百个服务后,带来了安全问题,Istio尝试在由服务组成的服务网格里,加入了一套全栈解决方案。这套方案里,Istio默默处理了大部分安全基础设施,但也暴露了认证和受权两个功能让用户进行自定义配置。咱们经过Policy、MeshPolicy以及RbacConfig、ServiceRole、ServiceRoleBinding就能够完成对认证和受权环节全部功能的配置,而不须要侵入地改动任何服务的代码。