深入了解双向 TLS

通过此任务,您可以仔细查看双向 TLS 并了解其设置。此任务假定:

ZipZip

  1. $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@)
  2. $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@)

检查 Citadel 是否运行正常

Citadel 是 Istio 的密钥管理服务。Citadel 必须正常运行才能使双向 TLS 正常工作。使用以下命令验证 Citadel 在集群中是否正确运行:

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

如果 “AVAILABLE” 列值为 1,则说明 Citadel 已经成功运行。

校验密钥和证书的安装情况

Istio 会为所有开启双向 TLS 的 sidecar 容器自动安装身份验证所必要的密钥和证书。运行以下命令确认 /etc/certs 下存在密钥和证书文件:

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

cert-chain.pem 是 Envoy 的证书,会在需要的时候提供给对端。而 key.pem 就是 Envoy 的私钥,和 cert-chain.pem 中的证书相匹配。root-cert.pem 是用于证书校验的根证书。这个例子中,我们集群中只部署了一个 Citadel,所以所有的 Envoy 共用同一个 root-cert.pem

使用 openssl 工具来检查证书的有效性(当前时间应该处于 Not BeforeNot After 之间)

  1. $ 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
  2. Validity
  3. Not Before: May 17 23:02:11 2018 GMT
  4. Not After : Aug 15 23:02:11 2018 GMT

还可以查看一下客户端证书的 SAN(Subject Alternative Name)

  1. $ 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
  2. X509v3 Subject Alternative Name:
  3. URI:spiffe://cluster.local/ns/default/sa/default

请参阅 Istio 认证 一节,可以了解更多服务认证方面的内容。

检查 istio 双向 TLS 认证的配置

您可以使用 istioctl 工具检查有效的双向 TLS 设置。标识用于的身份验证策略和目标规则httpbin.default.svc.cluster.local 配置和使用的模式,使用以下命令:

  1. $ istioctl authn tls-check httpbin.default.svc.cluster.local

在以下示例输出中,您可以看到:

  • 在 8080 端口上始终为 httpbin.default.svc.cluster.local 设置双向 TLS。
  • Istio 使用网格范围的 default 身份验证策略。
  • Istio 在 default 命名空间中有 default 目的地规则。
  1. HOST:PORT STATUS SERVER CLIENT AUTHN POLICY DESTINATION RULE
  2. httpbin.default.svc.cluster.local:8080 OK mTLS mTLS default/ default/default

输出显示:

  • STATUS:服务器,本例中的 httpbin 服务和调用 httpbin 的客户端之间的 TLS 设置是否一致。

  • SERVER:服务器上使用的模式。

  • CLIENT:客户端或客户端使用的模式。

  • AUTHN POLICY:身份验证策略的名称和命名空间。如果策略是网格范围的策略,则命名空间为空,如本例所示:default/

  • DESTINATION RULE:使用的目标规则的名称和名称空间。

为了说明存在冲突的情况,请为具有错误 TLS 模式的 httpbin 添加特定于服务的目标规则:

  1. $ cat <<EOF | istioctl create -n bar -f -
  2. apiVersion: "networking.istio.io/v1alpha3"
  3. kind: "DestinationRule"
  4. metadata:
  5. name: "bad-rule"
  6. spec:
  7. host: "httpbin.default.svc.cluster.local"
  8. trafficPolicy:
  9. tls:
  10. mode: DISABLE
  11. EOF

运行与上面相同的 istioctl 命令,您现在看到状态为 CONFLICT ,因为客户端处于 HTTP 模式,而服务器处于 mTLS

  1. $ istioctl authn tls-check httpbin.default.svc.cluster.local
  2. HOST:PORT STATUS SERVER CLIENT AUTHN POLICY DESTINATION RULE
  3. httpbin.default.svc.cluster.local:8080 CONFLICT mTLS HTTP default/ bad-rule/default

您还可以确认从 sleephttpbin 的请求现在已失败:

  1. $ 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'
  2. 000
  3. command terminated with exit code 56

在继续之前,请使用以下命令删除错误的目标规则以使双向 TLS 再次起作用:

  1. $ kubectl delete --ignore-not-found=true bad-rule

验证请求

此任务显示具有双向 TLS 的服务器如何启用对以下请求的响应:

  • 使用明文请求中(即 HTTP 请求)
  • 使用 TLS 但没有客户端证书
  • 使用 TLS 和客户端证书要执行此任务,您需要绕过客户端代理。最简单的方法是从 istio-proxy 容器发出请求。

  • 确认明文请求请求失败,因为需要 TLS 使用以下命令与 httpbin 对话:

  1. $ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl http://httpbin:8000/headers -o /dev/null -s -w '%{http_code}\n'
  2. 000
  3. command terminated with exit code 56

请注意,退出代码为 56,代表无法接收网络数据。

  • 确认没有客户端证书的 TLS 请求也会失败:
  1. $ 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' -k
  2. 000
  3. command terminated with exit code 35

这次,退出代码为 35,这对应于 SSL/TLS 握手中某处发生的问题。

  • 使用客户端证书确认 TLS 请求成功:
  1. $ 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
  2. 200

Istio 使用 Kubernetes Service Account 作为服务标识,提供比服务名称更强的安全性(有关更多详细信息,请参阅 Istio 身份)。因此,Istio 使用的证书没有注明服务名称,但是 curl 需要利用这些信息验证服务器的身份。为了防止 curl 客户端报错,我们使用 curl-k 参数。该参数可跳过客户端对服务器名称的验证,例如,httpbin.default.svc.cluster.local 服务器提供的证书。

清理

ZipZip

  1. $ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@
  2. $ kubectl delete --ignore-not-found=true -f @samples/sleep/sleep.yaml@

相关内容

通过 HTTPS 进行双向 TLS

展示如何在 HTTPS 服务上启用双向 TLS。

基于 Istio 的 Micro-Segmentation 授权

描述 Istio 的授权功能以及如何在各种用例中使用它。

Citadel 的健康检查

如何在 Kubernetes 中启用 Citadel 的健康检查。

HTTP 服务的访问控制

展示为 HTTP 服务设置基于角色的访问控制方法。

Istio Service 健康检查

展示如何对 Istio service 进行健康检查。

Istio Vault CA 集成

有关如何整合 Vault CA 到 Istio 中颁发证书的教程。