@liuhui0803
2018-08-22T13:57:26.000000Z
字数 4743
阅读 1693
开发
架构和设计
DevOps
安全
微服务
摘要:
Istio正试图解决通过云平台运行应用程序时可能面临的一些非常困难的挑战:应用程序网络、可靠性、可观测性以及(本文重点介绍的)安全性。借助Istio,网格中不同服务之间的通信将变得更安全,并且默认便会被加密。Istio还有助于解决“源头”和“最终用户”的JWT标识令牌验证问题。
正文:
主要结论
- Istio意在让“服务网格(Service Mesh)”这个概念变得更具体、更好理解,最新发布的Istio 1.0有望获得业界的广泛关注。
- Istio试图解决通过云平台运行应用程序时可能面临的一些困难挑战:应用程序网络、可靠性以及可观测性。
- Istio还希望解决安全性这个问题。借助Istio,网格中不同服务间的通信将更安全,并默认加密。
- Istio还有助于解决“源头”和“最终用户”的JWT标识令牌验证问题。
- 这些基础的安全功能可以帮助我们构建“零信任”网络,借此根据标识、上下文情境以及具体情况来分配信任,而不再让“调用方恰巧位于同一个内部网络中”。
Istio意在让“服务网格”这个概念变得更具体、更好理解,最新发布的Istio 1.0有望获得业界的广泛关注。InfoQ之前的文章中,Jasmine Jaksic曾经详细介绍了Istio和服务网格,因此本文我想重点介绍Istio在安全领域采取的措施,这些功能将会为云服务的开发和运维人员提供巨大价值。
Istio试图解决通过云平台运行应用程序时可能面临的一些困难挑战。具体来说,Istio主要解决了应用程序网络、可靠性和可观测性等问题。以往我们通常会使用预构建的应用程序库来应对这些挑战,如断路器、客户端负载均衡、指标集(Metrics collection)等。然而跨越不同语言、框架、运行时等内容这样做,会造成大部分组织都无法承受的运营负担。
此外,这种做法也很难确保在每种语言的实现中维持一致,更不用提需要改动或修复Bug时用固定的步骤将它们一次升级到位了。围绕可靠性、可观测性以及策略的实施会遇到大量挑战,任何企业无一例外都会面临类似情况。虽然不同企业面临的问题基本类似,但如果不加以重视都会对业务造成巨大应向,因此必须妥善解决。Istio的目标就是解决这些难题。
对应用程序团队来说,安全性是另一个共同面临,并且难以解决的问题。某些情况下,安全性只是一种事后想法,而我们往往会在最后一刻试图将它硬塞进自己的应用中。为什么?因为安全性很难做到足够好。举例来说,诸如“加密应用程序流量”这种基本工作应该很常见并且很简单,对吧?在服务端配置TLS/HTTPS也应该很简单,对吧?甚至之前的项目中可能很早就这样做过了。然而在我看来,做的到底是否正确,就不那么好判断了。加密是否使用了正确的证书?证书是否由客户端认可的CA颁发?是否选择了正确的加密算法?是否将其正确导入至证书存储/密钥库?难道不是直接在TLS/HTTPS配置中启用“—insecure”标记就行了吗?
此类错误的配置可能非常危险。Istio则能提供必要帮助。Istio会在负责处理应用程序网络流量的每个应用程序实例旁部署(基于Envoy代理的)旁侧代理(Sidecar proxy)。当应用程序试图与http://foo.com
通信时,将通过这个旁侧代理(使用环回网络接口)通信,随后Istio会将通信重定向至另一个服务的旁侧代理,并最终将通信代理至实际的上游http://foo.com
。通过在请求路径上放置这些代理,即可实现类似不被应用程序知晓的透明自动加密等操作。借此无需要求每个应用程序的开发团队“做正确的事”,一样可以实现一致的流量加密。
在配置和维护TLS以及为服务架构搭建共用的TLS过程中,证书的管理也是难题之一。Istio的控制界面提供了Citadel组件,可以用于管理应用程序实例的证书和密钥。Citadel能够生成供每个工作负载表明自身身份所需的证书和密钥,并能定期更换,这样任何被攻陷的证书都会尽快失效。借助这样的证书,支持Istio的集群就可以自动获得共用的TLS。当然用户也可以在必要时加入自己的CA提供商根证书。
借助Istio,网格中不同服务间的通信将更安全,并默认加密。用户无需折腾证书和CA证书链即可获得能投入实用的TLS。运营商也不再需要祈祷每位开发者正确实现并配置自己的TLS/HTTPS设置。这一切都可以通过Istio的配置自动实现。
Istio在配置方面采取了与Kubernetes类似的路径。实际上,在Kubernetes中,我们可以通过Kubernetes Custom Resource Definition(CRD)对象配置Istio。用于配置Istio安全策略的两个重要对象包括Policy和DestinationRule对象。Policy对象可配置服务(或一组服务)的安全设置,例如,若要配置Kubernetes中运行的一个客户名称空间中的所有服务,可以使用下列Policy对象:
apiVersion: “authentication.istio.io/v1alpha1”
kind: “Policy”
metadata:
name: “default”
namespace: “customer”
spec:
peers:
通过上述配置,该客户名称空间中运行的所有服务均会接受使用mTLS的传入流量。但为了使用mTLS,我们还需要告诉客户端在调用服务时使用mTLS。为此可以使用Istio的DestinationRule对象。Istio中的DestinationRule可用于配置客户端与服务的通信方式,我们可以在DestinationRule中指定很多设置,如断路器、负载均衡和TLS。若要启用mTLS,可使用下列配置:
apiVersion: “networking.istio.io/v1alpha3”
kind: “DestinationRule”
metadata:
name: “default”
namespace: “foo”
spec:
host: “*.customer.svc.cluster.local”
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
上述DestinationRule会要求客户端在发出调用,与客户名称空间中的服务通信时使用mTLS。我们还可以将TLS模式配置为ISTIO_MUTUAL,这意味着我们允许让Istio管理证书和密钥,并将其载入服务(使用Kubernetes中的Kubernetes机密),随后服务代理即可用它们来发起TLS通信。如果希望自行控制客户端证书,则可使用MUTUAL模式,并通过磁盘位置提供证书,这样客户端即可找到所需证书和私钥。
按照上述方式使用mTLS时,不仅可以加密连接,并且更重要的是可以清楚地知道谁在调用谁。Istio使用了Secure Production Identity Framework for Everyone(SPIFFE)规范,标识可直接编码到mTLS使用的证书中。通过这样的方式,当服务B与服务A通信时,服务A就可以确认服务B的真实身份。我们可以针对这些标识编写规则,借此决定服务网格必须应用的规则或策略。举例来说,如果服务A不允许与服务B通信,即可在每个应用程序旁侧运行的代理中,使用建立mTLS所必须的标识来实施这样的策略。
但如果服务A是代表用户X向服务B发出请求又会怎样?如果服务A有权调用并访问服务B来执行某些操作(例如检查账户余额),但用户X无权这样做,如何确认并实现这一目标?在服务架构中,服务与最终用户或来源标识(登录的用户)进行通信的典型方式是传递标识令牌,例如JSON Web Token。这些令牌可以代表已经通过身份验证的用户以及这些用户的主张。
Istio有助于实现“来源”或“最终用户”JWT标识令牌的验证。以往这也是个非常麻烦的领域,因为不同的应用程序语言/框架组合使得我们很难通过库来处理验证工作并解包JWT令牌。举例来说,在流行的Keycloak Identity和SSO项目中,为了处理这类操作,甚至为每种流行的语言提供了语言插件。但如果使用Istio,就可以更自由地实现这一切。例如,若要配置Istio在请求中使用mTLS,同时验证JWT令牌(如果令牌不存在、无效或过期,则让请求失败),我们可以配置Policy对象。毕竟Policy对象就是用于指定希望服务表现出的行为的:
apiVersion: “authentication.istio.io/v1alpha1”
kind: “Policy”
metadata:
name: “customer-jwt-policy”
spec:
targets:
- name: customer
peers:
- mtls:
origins:
- jwt:
issuer: http://keycloak:8080/auth/realms/istio
jwksUri: http://keycloak:8080/auth/realms/istio/protocol/openid-connect/certs
principalBinding: USE_ORIGIN
通过上述配置,如果客户端试图连接至客户的服务,除非JWT身份验证成功,否则请求将无法到达服务。使用Istio的另一个优势在于请求依然可获得mTLS的保护,借此可保护JWT令牌不被泄露并用于某种类型的重播攻击。
本文介绍了在构建云原生应用过程中,Istio在改善安全性方面提供的几种方法。通过在服务相互之间,以及与来源/最终用户通信过程中使用强标识机制,我们可以编写出一些非常强大的访问控制规则,借此对系统行为加以约束。这些基本功能为“零信任”网络的搭建奠定了基础。在零信任网络中,我们可以根据标识、上下文情境以及具体情况来分配信任,而不再让“调用方恰巧位于同一个内部网络中”。随着逐渐步入全面互联模式以及混合云部署模式,我们也需要重新思考如何以最佳方式让整个架构获得安全性。Istio可以解决当今架构所面临的很多挑战,并在未来提供更丰富的选项。
Istio提供了非常强大的功能,服务团队可以借此解决自己面临的很多问题。它还提供了实用的API与配置对象,借此可在应用程序服务之外进行配置。以高度去中心化方式实现的这一切面对故障将获得更高弹性。如果你需要构建服务网格,并且希望实现一致的高安全性,那么Istio值得一试。
Christian Posta(@christianposta)是Red Hat的云应用程序首席架构师,并以图书作者(Introducing Istio Service Mesh,O’Reilly 2018;Microservices for Java Developers,O’Reilly 2016)、博主、演讲人、开源传道士,以及包括Istio、Apache ActiveMQ、Fabric8等在内众多开源项目贡献者的身份闻名于社区。Christian在大规模企业有多年工作经验,现在致力于帮助企业创建并部署大规模、高弹性、分布式架构,也就是现在我们所说的微服务。他喜欢辅导、培训并领导团队从事有关分布式系统、微服务、DevOps、云原生应用程序设计的项目。
作者:Christian Posta,阅读英文原文:Increasing Security with a Service Mesh: Christian Posta Explores the Capabilities of Istio