1

Istio提供双向TLS作为服务到服务身份验证的解决方案。

双向认证是指双方同时进行认证,这是某些协议的默认认证方式。以前称为“相互实体认证” ,因为两个或多个实体在传输任何数据或信息之前会验证对方的合法性。

下面是istio服务之间mTLS流:

  1. 客户端应用程序容器将纯文本HTTP请求发送到服务器。
  2. 客户端代理容器拦截出站请求。
  3. 客户端代理与服务器端代理执行TLS握手。此握手包括证书交换。这些证书由Istio预加载到代理容器中。
  4. 客户端代理对服务器的证书执行安全命名检查,以验证授权身份正在运行服务器。
  5. 客户端和服务器建立相互TLS连接,服务器代理将请求转发到服务器应用程序容器。

实现细节

从Istio 1.5开始,Istio使用自动双向TLS。这意味着,尽管服务同时接受纯文本和TLS通信,但默认情况下,服务将在集群内发送TLS请求。

与其他Istio配置一样,您可以在.yaml文件中指定身份验证策略。您使用kubectl部署策略。以下示例身份验证策略指定带有app: reviews标签的工作负载的传输身份验证必须使用双向TLS:

apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
  name: "example-peer-policy"
  namespace: "foo"
spec:
  selector:
    matchLabels:
      app: reviews
  mtls:
    mode: STRICT

作用域

在Istio中,可以通过三个粒度级别定义mTLS设置。对于每种服务,Istio都会应用最窄的匹配策略。顺序为:服务特定,命名空间范围,网格范围。

  • 网格范围:为根名称空间指定的策略,不带有或带有空的选择器字段。
  • 命名空间范围:为没有或没有空选择器字段的非根名称空间指定的策略。
  • 服务特定:在常规名称空间中定义的策略,带有非空选择器字段。

例如我们上面的示例就是一个服务特定的策略。

每个命名空间只能有一个网格范围的对等身份验证策略,并且只能有一个命名空间范围的对等身份验证策略。当您为同一网格或名称空间配置多个网格范围或命名空间范围的对等身份验证策略时,Istio会忽略较新的策略。当多个特定于工作负载的对等身份验证策略匹配时,Istio将选择最旧的策略。

模式

对等身份验证策略指定Istio对目标工作负载实施的双向TLS模式。支持以下模式:

  • PERMISSIVE:工作负载接受双向TLS和纯文本流量。当没有Sidecar的工作负载无法使用双向TLS时,此模式在迁移过程中最有用。通过使用sidecar注入迁移工作负载后,您应该将模式切换为STRICT
  • STRICT:工作负载仅接受双向TLS通信。、
  • DISABLE:相互TLS已禁用。从安全角度来看,除非您提供自己的安全解决方案,否则不应使用此模式。

取消设置模式时,将继承父作用域的模式。缺省情况下,未设置模式的网格范围对等身份验证策略使用PERMISSIVE模式。

此时,您可以在Istio中将任何服务设置为任何mTLS模式。但是,让我们看一下In mesh(从网格内)或out of mesh(网格外)调用服务时每种模式会发生什么情况?

In mesh 表示Sidecar代理在应用程序容器旁边运行。Out of mesh意味着没有Sidecar容器。

总结的表格如下:

  • PERMISSIVE 在网格内使用mTLS,在网格外使用纯文本连接
  • STRICT 在网格内使用mTLS,但拒绝来自网格外的连接
  • DISABLED 在网格内外都使用纯文本连接

Demo

该demo,我们会创建两个服务,分别检查未启用和启用对等身份验证策略的服务访问情况。

首先部署demo中需要的资源等:

kubectl create ns foo
kubectl label namespace foo istio-injection=enabled
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/httpbin/httpbin.yaml -n foo
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/sleep/sleep.yaml -n foo

sleep 应用程序是我们本次demo的客户端。httpbin 应用程序是我们本次demo的服务端。

我们查看一下访问情况,exec 到 sleep pod,然后对 httpbin pod 执行 curl:

curl http://httpbin:8000

<!DOCTYPE html>
<html lang="en">
......

访问成功。正如前面讲到的,istio1.5 之后自动mtls。在未设置特殊对等策略下,是可以接受纯文本请求。

接下来我们设置一个命名空间级别的对等策略,并且模式为严格:

apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: foo
spec:
  mtls:
    mode: STRICT

允许名称空间foo下所有工作负载的mTLS通信。

使用kubectl 将该策略应用到集群。

kubectl apply -f policy.yaml
peerauthentication.security.istio.io/default created

接着我们再次进入到sleep pod,对 httpbin pod 执行 curl:

curl http://httpbin:8000

<!DOCTYPE html>
<html lang="en">
......

访问依旧可以成功,这不是说明了我们对等策略没有生效。因为sleep 程序在mesh当中。

接下来,我们部署一个没有sidecar的sleep程序,即我们检测mesh外应用访问情况,我们另外创建了一个命名空间legacy,并且没有对其作istio-injection=enabled 标签处理,从而告诉istio忽略该命名空间应用。

kubectl create ns legacy
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.7/samples/sleep/sleep.yaml -n legacy

我们进入到legacy命名空间下的sleep pod,对 httpbin pod 执行 curl:

curl http://httpbin.foo:8000
curl: (56) Recv failure: Connection reset by peer

访问失败。因为我们对foo命名设置了严格模式的mTLS策略。纯文本请求将不被允许,因为身份验证失败。

当然我们此时可以删除创建的严格对等策略,之后访问恢复正常。


iyacontrol
1.4k 声望2.7k 粉丝

专注kubernetes,devops,aiops,service mesh。