服务网格 微服务
我看到许多客户转向微服务(无论他们是否应该在不同的职位上讨论主题 ),这样做时,他们正在尝试解决一些困难的组织扩展问题。 但是,使用微服务架构的细节通常会将一些旧问题换成新问题。 我与之交谈的大多数客户都有一个既可以在内部部署架构又可以在其架构上部署公共云的策略。 将应用程序分解为较小的服务并具有多个部署站点/平台会带来一些重大挑战。 我认为,像Istio这样的服务网格实现旨在解决其中的一些挑战。 实际上,关于Istio和Service Mesh , 实际上我有很多话要说 ,所以请随时关注@christianposta ,以了解最新信息。
当您走这条路时,您将面临的一个挑战是:安全性。
我知道我知道。 作为开发人员,您可能已经对安全性产生了仇恨关系–微服务使情况变得更糟。 当我们将应用程序分解为较小的服务时,我们会增加攻击的表面积。 尽管这里有很多安全方面的内容(应用程序漏洞,平台漏洞,数据保护,传输/网络等),但我将主要集中在微服务之间如何通信以及出现的一些问题上。
传统上,我们假设网络边界/外围足以挽救我们。 也就是说,由于我们位于“受保护的内部网络”上,因此我们的应用程序不必在传输安全性方面考虑太多。 停下来想一想。 您是否使用SSL / TLS保护内部应用程序? 我们过去通过本地电话在一个整体中进行的所有通信现在都通过网络公开。 我们需要做的第一件事是加密所有内部流量。 如果您要在传输中使用不带TLS的微服务,则可能会遇到一些麻烦的安全问题。
一些成熟的客户已经实现了加密所有微服务流量的能力,但并非没有很大的成本。 站起来使用公钥基础结构,发布密钥和证书,安装,旋转它们等都是相当昂贵的考验。 不用担心尝试配置正确的信任库/密钥库(Java),正确的SSL算法,确保您拥有正确的证书链等来带来的麻烦。我个人浪费了很多时间来尝试使此“正确” 。 然后,当您正确使用它时,您再也不想碰它了。
我还看到过这样的情况:开发人员先使用SSL / TLS,然后将其代码部署到IST / UAT等中,却发现他们在较低环境中拥有的安全配置不起作用。 为了将事情推向生产,他们急忙进行诸如禁用TLS验证之类的事情。 哎哟。
像Istio这样的服务网格将其简化了很多。 使用Istio,应用程序的所有实例都具有自己的sidecar容器。 该Sidecar充当所有传出和传入网络流量的服务代理。
使用此服务代理实现的众多好处中,与本次讨论相关的一项好处是能够透明地进行TLS加密。 这意味着位于请求路径中的代理与应用程序并置,它们负责加密流量。 您的应用程序可以没有证书,信任库,密钥库等。 Istio使证书和密钥向服务的交付自动化,代理使用它们对流量进行加密(提供双向TLS),并且Istio定期将密钥/证书轮换以减少遭受破坏的风险。
以Istio在Kubernetes上运行为例,每当部署应用程序时,都应分配一个应用程序应在其下运行的服务帐户-之后,istio会处理其余的工作。 Istio将为您的服务帐户创建一个证书/密钥对,并使用根CA密钥对证书进行签名,并在Kubernetes中将证书/密钥作为密钥颁发。 此秘密将安装到运行应用程序和Istio服务代理的Pod中,服务代理将使用cert / keys建立mTLS。
微服务的另一个安全问题是令人困惑的代理问题 。 在这种情况下,最终用户已要求服务代表它做某事。 在这种情况下,可以授权该服务执行此操作,但是可能不授权特定用户。 我们应该以某种方式将用户身份纳入方程式,并根据该身份评估授权。 一种实现方法是使用价值令牌,例如JWT 。
关于此事有几点要说:
首先,如果您要以明文方式传递JWT令牌(不使用TLS / mTLS),那么您将面临重大麻烦。 这些令牌默认情况下未加密(仅经过签名),可以轻松地将其选中并重播到您的服务中。 同样,这是Istio mTLS可以提供帮助的地方。 但是即使启用了mTLS,令牌也可能以另一种方式泄漏(我已经看到了将它们硬编码为src代码!!)。 如果您所有的服务都将JWT传递给其他所有服务,则您将再次面临重播问题。
其次,如果您尝试对所有微服务进行JWT验证,则会遇到与弹性库相同的问题 。 每个服务都有自己的库和自己的JWT验证实现。 即使像JBoss Keycloak这样的项目提供了出色的多语言支持,它也确实给库维护者以及依赖于这些库的应用程序开发人员带来了负担。 确保正确,一致且统一地实施它们是一项充满问题的壮举。
值得庆幸的是,Istio可以在这两个方面提供帮助。
首先,Istio可以为您自动进行JWT验证,而不管应用程序框架/语言如何。 您可以定义一个EndUserAuthenticationPolicySpec
,它配置将用于验证的身份提供者/凭据提供者 :
---
apiVersion: config.istio.io/v1alpha2
kind: EndUserAuthenticationPolicySpec
metadata:
name: cars-api-auth-policy
namespace: tutorial
spec:
jwts:
- issuer: http://keycloak:8080/auth/realms/istio
jwks_uri: http://keycloak.tutorial:8080/auth/realms/istio/protocol/openid-connect/certs
audiences:
- cars-web
然后,您可以将其绑定到特定服务:
---
apiVersion: config.istio.io/v1alpha2
kind: EndUserAuthenticationPolicySpecBinding
metadata:
name: cars-api-auth-policy-binding
namespace: tutorial
spec:
policies:
- name: cars-api-auth-policy
namespace: tutorial
services:
- name: cars-api
namespace: tutorial
注意: 此示例来自我的同事 Kamesh Sampath 。 在此配置中,我们将Keycloak设置为JWT令牌的身份管理者和颁发者(遵循OpenID Connect)。 有关更多信息, 请参见此博客 。 当呼叫进入服务时,如果没有JWT Bearer令牌,则将拒绝该呼叫。 此配置将安装一个Envoy jwt过滤器 ,该过滤器实际上负责验证JWT的签名:
最后,如何传播JWT令牌?
默认情况下,Istio将仅传播JWT令牌一跳。 它将获取JWT令牌的正文,并将其传递到单独的标头中的应用程序。 JWT主体将在sec-istio-auth-userinfo
标头中发送。 应用程序有责任根据最终用户的身份和服务的身份重新提交新令牌。 这样,我们可以将令牌的作用域限定为一次性使用,而不是在各处传播JWT。 对此的实现仍在发展中,我强烈建议您在此处和此处继续进行 。
现在就这样。 随着Istio中的安全故事的加强,我一定会跟进。 跟随我, 关注@christianposta,以获取有关微服务,Service Mesh,Istio等的最新信息。
翻译自: https://www.javacodegeeks.com/2018/03/how-a-service-mesh-can-help-with-microservices-security.html
服务网格 微服务