7.3.2 认证策略示例

如上节所述,默认情况下Istio提供了一个许可模式的网格范围的认证策略,即模式为PERMISSIVE。执行下面这个示例之前,请确保当前环境的网格范围的认证策略为许可模式,或者执行如下命令(可以从authpolicy/sample文件夹中的permissive.yaml中获取):


kubectl apply -f - <<EOF
apiVersion: "authentication.istio.io/v1alpha1"
kind: "MeshPolicy"
metadata:
  name: "default"
spec:
  peers:
  - mtls: 
        mode: PERMISSIVE
EOF

接着,创建命名空间ns1与ns2,并添加标签istio-injection,值为enabled:


kubectl create namespace ns1
kubectl label namespace ns1 istio-injection=enabled
kubectl create namespace ns2
kubectl label namespace ns2 istio-injection=enabled

以下示例中使用的yaml文件可以从目录authpolicy下的sample文件夹中获取,例如client.yaml位于目录authpolicy下的./sample/client.yaml,以此类推。

创建命名空间n1下的部署与服务:


kubectl apply -n ns1 -f client.yaml
kubectl apply -n ns1 -f server.yaml

创建命名空间n2下的部署与服务:


kubectl apply -n ns2 -f client.yaml
kubectl apply -n ns2 -f server.yaml

同时创建命名空间nosidecar,然后在该命名空间运行另外一个不带有Sidecar的客户端和服务端的应用,如下:


kubectl create namespace nosidecar
kubectl apply -n nosidecar -f client.yaml
kubectl apply -n nosidecar -f server.yaml

以下单行命令(可以从authpolicy/sample文件夹中的test1.sh中获取,执行前需要对该文件进行chmodtx授权)可以方便对所有客户端和服务端的组合进行检查:


for from in "ns1" "ns2" "nosidecar"; do for to in "ns1" "ns2" "nosidecar"; do 
kubectl exec $(kubectl get pod -l app=client -n ${from} -o jsonpath={.items..metadata.
name}) -c client -n ${from} -- curl "http://server.${to}:8000/ip" -s -o /dev/null -w "client.${from} to server.${to}: %{http_code}\n"; done; done

通过从任意客户端向任意服务端发送HTTP请求(可以使用curl命令),所有请求都应该成功进行并且返回HTTP状态码,其值为200,如下所示:


client.ns1 to server.ns1: 200
client.ns1 to server.ns2: 200
client.ns1 to server.nosidecar: 200
client.ns2 to server.ns1: 200
client.ns2 to server.ns2: 200
client.ns2 to server.nosidecar: 200
client.nosidecar to server.ns1: 200
client.nosidecar to server.ns2: 200
client.nosidecar to server.nosidecar: 200

之后,通过执行如下命令(可以从authpolicy/sample文件夹中的mtls.yaml中获取)将网格范围的认证策略设置为双向认证模式,此策略指定网格中的所有工作负荷仅接受使用TLS的加密请求:


kubectl apply -f - <<EOF
apiVersion: "authentication.istio.io/v1alpha1"
kind: "MeshPolicy"
metadata:
  name: "default"
spec:
  peers:
  - mtls: {}
EOF

执行上述同样的命令,通过从任意客户端向任意服务端发送HTTP请求,会发现在Istio服务(即那些带有Sidecar的服务)之间的请求都将失败并显示错误代码503,原因是客户端仍在使用明文请求。但是不带有Sidecar的服务之间或者对不带有Sidecar的服务的调用,这些请求都不受影响,可以成功进行并且返回的HTTP状态码为200,如下所示:


client.ns1 to server.ns1: 503
client.ns1 to server.ns2: 503
client.ns1 to server.nosidecar: 200
client.ns2 to server.ns1: 503
client.ns2 to server.ns2: 503
client.ns2 to server.nosidecar: 200
client.nosidecar to server.ns1: 000
command terminated with exit code 56
client.nosidecar to server.ns2: 000
command terminated with exit code 56
client.nosidecar to server.nosidecar: 200

客户端也使用双向TLS,就需要设置目标规则。执行如下所示命令(可以从authpolicy/sample文件夹中的dr_mutual.yaml中获得),主机值*.local仅限于与集群中的服务匹配,在ISTIO_MUTUAL TLS认证模式中,Istio将根据其内部实现设置密钥和证书的路径。


kubectl apply -f - <<EOF
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "default"
  namespace: "default"
spec:
  host: "*.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
EOF

重新运行测试命令,你将看到Istio服务之间的所有请求现已成功完成,但从非Istio服务请求Istio服务却全部失败,返回command terminated with exit code 56。这是由于Envoy拒绝了明文请求,因此curl会以错误代码56(接收网络数据失败)退出。

此外,从Istio服务请求非Istio服务也会失败,并返回503错误代码。


client.ns1 to server.ns1: 200
client.ns1 to server.ns2: 200
client.ns1 to server.nosidecar: 503
client.ns2 to server.ns1: 200
client.ns2 to server.ns2: 200
client.ns2 to server.nosidecar: 503
client.nosidecar to server.ns1: 000
command terminated with exit code 56
client.nosidecar to server.ns2: 000
command terminated with exit code 56
client.nosidecar to server.nosidecar: 200

当然可以通过添加目标规则来覆盖server.nosidecar的TLS设置,如下:


kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
 name: "server-nosidecar"
spec:
 host: "server.nosidecar.svc.cluster.local"
 trafficPolicy:
   tls:
     mode: DISABLE
EOF

再次运行测试命令,你将看到从Istio服务请求非Istio服务已成功完成,并返回200代码。


client.ns1 to server.ns1: 200
client.ns1 to server.ns2: 200
client.ns1 to server.nosidecar: 200
client.ns2 to server.ns1: 200
client.ns2 to server.ns2: 200
client.ns2 to server.nosidecar: 200
client.nosidecar to server.ns1: 000
command terminated with exit code 56
client.nosidecar to server.ns2: 000
command terminated with exit code 56
client.nosidecar to server.nosidecar: 200