Testing Mutual TLS(0.8)

通过这个task,你将学会如何:

  • 核实Istio内彼此之间的TLS身份认证设置
  • 手动测试身份认证

Before you begin

这个task假设你有一个k8s集群:

  • 安装Istio并开启全局互相TLS认证:
kubectl apply -f install/kubernetes/istio-demo-auth.yaml

或使用 Helm 将 global.mtls.enabled 设为true

如果用Istio 0.7,你可以使用 authentication policy 去配置一个命名空间的所有/选择的服务开启互相TLS(重复所有命名空间以获取全局设置)。详情请看 authentication policy task

  • 对于demo,部署带有sidecar的 httpbin 及 sleep 。为了方便,demo都在命名空间default 上。如果你希望使用不同的命名空间,请在下节示例命令中适当加上 -n yournamespace
kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml)

Verifying Istio’s mutual TLS authentication setup

Verifying Citadel

验证集群级的Citadel正在运行:

kubectl get deploy -l istio=citadel -n istio-system
NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
istio-citadel   1         1         1            1           1m

如果 “AVAILABLE” 列是1表示Istio Citadel启动。

Verifying service configuration
  • 检查安装模式。如果启用互相TLS是默认的(e.g 安装Istio时用 istio-demo-auth.yaml ),你可以在configmap中看到未注释的 authPolicy: MUTUAL_TLS
kubectl get configmap istio -o yaml -n istio-system | grep authPolicy | head -1
  • 检查认证策略。还可以通过身份验证策略(authentication policy)为每个服务启用(或禁用)相互TLS。策略(如果存在)将覆盖目标服务的configmap设置。不幸的是,除了检查适用命名空间中的所有策略之外,没有快速获取服务相关策略的方法。
kubectl get policies.authentication.istio.io -n default -o yaml
  • 检查目标规则。从Istio 0.8开始,目标规则的 traffic policy 用来配置客户端使用(或不使用)相互TLS。为了向后兼容,默认流量策略是从configmap标志推断的(即,如果 authPolicy: MUTUAL_TLSdefault 的流量策略也为 MUTUAL_TLS)。如果某些服务存在身份验证策略否决这个设置,它应该附带相应的目标策略。与身份验证策略类似,验证设置的唯一方法是手动检查所有规则:
kubectl get destinationrules.networking.istio.io --all-namespaces -o yaml

目标规则范围模型不仅限于命名空间。因此有必要检查所有命名空间中的规则。

Verifying keys and certificates installation

Istio在所有sidecar容器中自动安装互相TLS认证所需的密钥和证书。

kubectl exec $(kubectl get pod -l app=httpbin -o jsonpath={.items..metadata.name}) -c istio-proxy -- ls /etc/certs
cert-chain.pem
key.pem
root-cert.pem

cert-chain.pem 是Envoy的证书,需要交给另一方。key.pem 是Envoy的私钥,与cert-chain.pem 中的Envoy证书匹配。root-cert.pem 是验证peer证书的根证书。在此示例中,我们在集群中只有一个Citadel,因此所有Envoys都具有相同的 root-cert.pem

使用oppenssl 工具检查证书是否生效(当前时间应该在 Not BeforeNot After 之间)

kubectl exec $(kubectl get pod -l app=httpbin -o jsonpath={.items..metadata.name}) -c istio-proxy -- cat /etc/certs/cert-chain.pem | openssl x509 -text -noout  | grep Validity -A 2
Validity
        Not Before: May 17 23:02:11 2018 GMT
        Not After : Aug 15 23:02:11 2018 GMT

你也可以检查客户端证书的identity

扫描二维码关注公众号,回复: 2106607 查看本文章
kubectl exec $(kubectl get pod -l app=httpbin -o jsonpath={.items..metadata.name}) -c istio-proxy -- cat /etc/certs/cert-chain.pem | openssl x509 -text -noout  | grep 'Subject Alternative Name' -A 1
X509v3 Subject Alternative Name:
    URI:spiffe://cluster.local/ns/default/sa/default

secure naming 中查看更多Istio的服务标识信息。

Testing the authentication setup

假设正确启用了相互TLS身份验证,当双方都拥有Envoy sidecar时,它不应影响从一服务到另一服务的通信。但是,没有sidecar的pod请求或没有客户端证书的sidecar直接请求应该会失败。下面例子说明了此行为。

1.请求从sleep 应用容器到httpbin 服务应该成功(返回 200

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl httpbin:8000/headers -o /dev/null -s -w '%{http_code}\n'

200

2.另一方面,从sleep proxy 容器到httpbin 服务的请求就会失败,因为请求没有使用TLS,也不提供客户端证书。

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl httpbin:8000/headers -o /dev/null -s -w '%{http_code}\n'

000
command terminated with exit code 56

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://httpbin:8000/headers -o /dev/null -s -w '%{http_code}\n'

000
command terminated with exit code 77

3.但是,提供客户端证书就可以成功请求

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl https://httpbin:8000/headers -o /dev/null -s -w '%{http_code}\n' --key /etc/certs/key.pem --cert /etc/certs/cert-chain.pem --cacert /etc/certs/root-cert.pem -k

200


Istio使用 Kubernetes service accounts 作为服务身份,比服务名提供了更强的安全性(在 here 查看更多信息)。因此,Istio中使用的证书没有服务名称,这是curl 验证服务器身份所需的信息。因此,我们使用curl-k 选项来防止在服务器提供的证书中找不到也无法验证服务器名称(即httpbin.ns.svc.cluster.local)时中止curl客户端。

4.来自没有sidecar的pod的请求。为了这个demo,我们安装另一个没有sidecar的sleep 服务。为了避免名字冲突,我们将它放到不同的命名空间。

kubectl create ns legacy
kubectl apply -f samples/sleep/sleep.yaml -n legacy

5.等到pod状态变为Running 后,执行相似的curl 命令。该请求应该失败,因为pod中没有sidecar来帮助启动TLS通信。

kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name} -n legacy) -c sleep -n legacy -- curl httpbin.default:8000/headers -o /dev/null -s -w '%{http_code}\n'

000
command terminated with exit code 56

Cleanup

kubectl delete --ignore-not-found=true -f samples/httpbin/httpbin.yaml
kubectl delete --ignore-not-found=true -f samples/sleep/sleep.yaml
kubectl delete --ignore-not-found=true ns legacy

samples/httpbin/httpbin.yaml

samples/sleep/sleep.yaml

猜你喜欢

转载自blog.csdn.net/ybt_c_index/article/details/80888173