零信任Kubernetes和服务网格

2023-08-09 12:26:49 浏览数 (1)

作者:Flynn

如果你在Kubernetes中进行安全相关工作,很有可能你至少听说过“零信任”(zero-trust)的概念。你可能已经被要求部署它,或者至少思考如何部署它,毕竟大家都在谈论它!

因此,让我们简要讨论如何实际实现零信任安全策略。

零信任概述

简单回顾一下:零信任是一种模型,帮助我们确定是否信任给定的实体与另一个实体进行交互,它围绕着这样的思想:仅仅依赖边界安全是不够的,我们需要对每次访问、每个用户进行细粒度的检查。在云原生世界中,这是一个非常合适的方案,因为我们不再控制曾提供安全边界的硬件。

在工作负载层面处理这个需求最简单、最干净的方式,是安装一个服务网格。

服务网格和零信任

简单总结一下,服务网格是位于应用程序下方的软件层,为平台级别添加安全性、可观测性和可靠性功能,使应用程序开发人员能够专注于应用程序的业务需求。在云原生世界中,有多种可供选择的服务网格,包括开源和商业版本,如Linkerd、Istio、OpenServiceMesh等,它们都在不同程度上解决了相同的一组功能(当然,程度不同)。

服务网格通过将自身插入到集群网络堆栈中,以便在集群中调解和监控通信。在大多数情况下,它们通过在应用程序容器旁插入代理边车来实现。这听起来可能有些过多,但Kubernetes使得管理这一点变得简单且相对容易。一个重要的附加好处是,由于边车被放置在应用程序工作负载的Kubernetes Pod内部,它们继承了与应用程序本身相同的权限和访问权限,提供了明确的安全边界和操作简易性。

一旦代理就位,服务网格会重新配置Kubernetes网络,使应用程序Pod的所有通信都经过代理路由,让代理控制通信方式,并在没有对应用程序进行任何更改的情况下进行性能度量。服务网格通常可以自动进行诸如自动mTLS、强大的身份验证和授权策略执行、自动重试等等功能。它们是非常强大的工具,因为它们对应用程序中发生的通信具有极低级别、广泛的访问权限。

网格中的身份认证

关于在Kubernetes中实现零信任,一个重要的要点是我们不能依赖网络来确定身份,因为我们无法控制网络。相反,我们需要一些与工作负载本身相关联的工作负载身份,与网络没有任何关联。有几种不同的方法,但一个共同点是将工作负载身份基于用于该工作负载的Kubernetes ServiceAccount。Kubernetes从业者已经习惯了ServiceAccount的概念,因此每个工作负载可以很容易地拥有一个唯一的ServiceAccount,每个ServiceAccount都有一个相关联的唯一的ServiceAccountToken,工作负载可以访问该令牌。

我将使用Linkerd作为开源的CNCF-毕业级服务网格来提供一个具体的例子:对于每个工作负载,Linkerd使用其ServiceAccount令牌来加密引导TLS证书,为该特定的工作负载生成证书。然后,这些证书形成Linkerd在所有工作负载之间进行行业标准mTLS的基础。这使得Linkerd能够验证连接两端的工作负载的身份,并为所有工作负载之间的通信提供加密和完整性检查。

当我们谈论mTLS证书时,当然还需要讨论证书的信任链。这是每个网格都不同的另一个领域,但它们都提供了一种将信任链连接到外部CA的方式,以便将网格与组织现有的PKI(公钥基础设施)进行关联,并且所有这些网格都需要注意信任链中的证书!一种常见的技术是使用CNCF孵化项目cert-manager等工具,允许网格的根CA来自企业的PKI,并自动化网格的证书轮换。

继续以我们的Linkerd为例:Linkerd有一个两级信任链,其中信任锚证书签署了身份发行者证书,而后者又签署了工作负载证书。Linkerd通常使用cert-manager从系统(如Vault)中获取信任锚,并使用cert-manager直接管理身份发行者的轮换。

Linkerd本身需要访问身份发行者的公钥和私钥,但仅需要信任锚的公钥。通过这种方式限制访问在设置cert-manager时需要一些小心,但这是值得的;这样可以更安全地设置较长的信任锚到期时间,同时仍然可以轻松自动化身份发行者的频繁轮换,以提供更好的安全性。它还提供了一些与网络拓扑无关的优势;例如,如果两个集群共享相同的信任锚,则它们之间的安全通信是容易的。

当涉及工作负载身份时,请记住这是一个非常重要的方面,它与应用程序最终用户的身份是分开的,但同样至关重要。确保您能够准确地知道您与用户认证微服务进行通信,这是建立信任的第一步。如果您不能确定您正在与真正的认证服务交互,那么您可能无法完全信任从中获取的关于最终用户的信息。

策略

一旦我们解决了工作负载身份认证的问题,我们就可以转向策略来执行身份验证和授权。对于正确的零信任策略,我们需要特别注意最小特权原则:每个工作负载应该只拥有其所需的访问权限,而不多。然而,最小特权原则可能需要非常复杂的策略描述,例如,“API网关工作负载被允许从用户管理工作负载请求用户列表,但不允许尝试更新用户列表。”

将这样的检查写入应用程序工作负载当中是可能的。然而,这样做既昂贵又脆弱。所有应用程序开发人员需要每次都完美地完成它,而且你需要在更新策略时更新工作负载镜像。相反,让服务网格来处理这些任务可以将编写应用程序与保持策略描述最新保持分开。

不同的服务网格对此处理的方式有所不同,但这里最常见的机制是网格特定的策略CRD(自定义资源定义)。以Linkerd作为示例,以下是一组定义策略的Linkerd CRD。我们从一个HTTPRoute开始,它说明对于 /authors.json 或任何以 /authors/ 开头的 HTTP GET 请求,将由 authors 工作负载处理:


apiVersion: policy.linkerd.io/v1beta1 kind: HTTPRoute metadata: name: authors-get-route namespace: booksapp spec: parentRefs: – name: authors kind: Server group: policy.linkerd.io rules: – matches: – path: value: “/authors.json” method: GET – path: value: “/authors/” type: “PathPrefix” method: GET

接下来是一对Linkerd CRD,允许该路由仅由具有两个特定工作负载身份的工作负载使用:


apiVersion: policy.linkerd.io/v1alpha1 kind: AuthorizationPolicy metadata: name: authors-get-policy namespace: booksapp spec: targetRef: group: policy.linkerd.io kind: HTTPRoute name: authors-get-route requiredAuthenticationRefs: – name: authors-get-authn kind: MeshTLSAuthentication group: policy.linkerd.io


apiVersion: policy.linkerd.io/v1alpha1 kind: MeshTLSAuthentication metadata: name: authors-get-authn namespace: booksapp spec: identities: – “books.booksapp.serviceaccount.identity.linkerd.cluster.local” – “webapp.booksapp.serviceaccount.identity.linkerd.cluster.local”

当我们在booksapp命名空间中,books和webapp身份将能够从authors工作负载读取信息,但它们将无法以其他方式与authors进行交互。其他身份的工作负载将无法与authors工作负载进行任何交互,因为Linkerd的处理方式是,一旦将任何AuthorizationPolicy与路由关联,那么与该路由匹配的所有流量都必须匹配一个AuthorizationPolicy才能被允许通过。未经授权的流量将被拒绝。

值得注意的是,不同的服务网格在策略方面有一些不同的方式,但这个功能在所有网格中都是常见的:总有一种方法来精确定义哪些角色被允许使用路由(或整个工作负载),并确保规则得到遵守。

请记住,我们所讨论的是工作负载的身份验证和授权。这是确保应用程序安全的必要部分:你必须能够控制工作负载之间的交互方式,以对应用程序级别的安全性充满信心。试图在应用程序层面上完成所有这些工作是代价高昂且脆弱的,更好的做法是让网格处理它。

网格局限性

服务网格也有一些局限性,让我们谈谈它们无法解决的问题:

首先,网格主要关注的是传输过程中的安全性。例如,它对于数据静态存储的安全性没有帮助;网格可以确保对您的个人身份信息数据库的请求将被加密,但你仍然需要确保数据库将数据写入磁盘时也进行了加密。

此外,为了使网格发挥最大的作用,它需要了解你的工作负载使用的通信协议。这对于可靠性而言比安全性略有帮助,但在你使用标准协议(如HTTP或gRPC)进行通信时,大多数网格效果最好。

最后,正如我们之前提到过的,网格中的身份验证与你的应用程序中的身份验证不同。这是一个特性——即使你已登录的用户被允许在银行账户之间进行资金转移,集群中的天气应用程序工作负载也不应该能够操纵资金!有效的零信任安全性要求在两个级别进行检查:转移资金的请求应来自一个合理的工作负载,并代表具有适当权限的已登录用户进行。

服务网格可以独立解决工作负载层面的这个问题,但应用程序级别的策略是另一回事。在许多情况下,位于服务网格之上的API网关可以是将网格的安全性扩展到应用程序的有效方式。

零信任 Kubernetes 和服务网格

在云原生世界中重新思考安全性是一项艰巨的任务。我们需要改变如何管理身份认证,将策略与应用程序分开,并在平台层面管理所有这些,以使应用程序开发人员无需担忧。这可能是在紧迫的时间表下进行的,而且这将始终发生在一个必须降低成本并且不中断关键服务的世界中。

好消息是,Kubernetes用户有优势:将服务网格嵌入到应用程序中可以以非常低的成本轻松满足许多零信任需求。Kubernetes现有的侧车注入机制和动态重新配置容器网络机制非常强大:它们共同提供了一种优雅的方法,可以在不重写应用程序的情况下为其添加功能。

本文翻译自cloudnativenow.com

0 人点赞