自动双向 TLS

    借助 Istio 的自动双向 TLS 特性,您只需配置认证策略即可使用双向 TLS,而无需关注目标规则。

    Istio 跟踪迁移到 sidecar 的服务端工作负载,并将客户端 sidecar 配置为自动向这些工作负载发送双向 TLS 流量,同时将明文流量发送到没有 sidecar 的工作负载。这使您可以通过最少的配置,逐步在网格中使用双向 TLS。

    • 理解 Istio 认证策略和关于章节的内容。

    • 安装 Istio 时,配置 选项为 false,global.mtls.auto 选项为 true。以安装 demo 配置文件为例:

    本例中,我们部署 httpbin 服务到 fullpartiallegacy 三个命名空间中,分别代表 Istio 迁移的不同阶段。

    命名空间 full 包含已完成 Istio 迁移的所有服务器工作负载。每一个部署都有 Sidecar 注入。

    Zip

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

    命名空间 partial 包含部分迁移到 Istio 的服务器工作负载。只有完成迁移的服务器工作负载(由于已注入 Sidecar)能够使用双向 TLS 流量。

    Zip

    1. $ kubectl create ns partial
    2. $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n partial
    3. $ cat <<EOF | kubectl apply -n partial -f -
    4. apiVersion: apps/v1
    5. kind: Deployment
    6. metadata:
    7. name: httpbin-nosidecar
    8. spec:
    9. replicas: 1
    10. selector:
    11. matchLabels:
    12. app: httpbin
    13. template:
    14. metadata:
    15. labels:
    16. app: httpbin
    17. version: nosidecar
    18. spec:
    19. containers:
    20. - image: docker.io/kennethreitz/httpbin
    21. imagePullPolicy: IfNotPresent
    22. name: httpbin
    23. ports:
    24. - containerPort: 80
    25. EOF

    命名空间 legacy 中的工作负载,都没有注入 Sidecar。

    Zip

    1. $ kubectl create ns legacy
    2. $ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n legacy
    3. $ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy

    接着,我们部署两个 sleep 工作负载,一个有 Sidecar,另一个没有。

    Zip

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

    您可以确认在所有命名空间部署完成。

    1. $ kubectl get pods -n full
    2. $ kubectl get pods -n partial
    3. $ kubectl get pods -n legacy
    4. NAME READY STATUS RESTARTS AGE
    5. httpbin-dcd949489-5cndk 2/2 Running 0 39s
    6. sleep-58d6644d44-gb55j 2/2 Running 0 38s
    7. NAME READY STATUS RESTARTS AGE
    8. httpbin-6f6fc94fb6-8d62h 1/1 Running 0 10s
    9. httpbin-dcd949489-5fsbs 2/2 Running 0 12s
    10. NAME READY STATUS RESTARTS AGE
    11. httpbin-54f5bb4957-lzxlg 1/1 Running 0 6s
    12. sleep-74564b477b-vb6h4 1/1 Running 0 4s

    您还需验证系统中是否存在默认的网格验证策略,可以参考下面操作:

    最后但并非最不重要的一点是,确认没有应用于示例服务的目标规则。您可以通过检查已有目标规则的 host: 字段,并确保它们没有匹配我们的示例服务。例如:

    1. $ kubectl get destinationrules.networking.istio.io --all-namespaces -o yaml | grep "host:"
    2. host: istio-policy.istio-system.svc.cluster.local

    例如,这是一个检查 sleep.fullhttpbin.full 可达性的命令:

    1. URI=spiffe://cluster.local/ns/full/sa/sleep
    2. response 200

    SPIFFE URI 显示来自 X509 证书的客户端标识,它表明流量是在双向 TLS 中发送的。如果流量为明文,将不会显示客户端证书。

    从 PERMISSIVE 模式开始

    这里,我们从开启网格服务双向 TLS 的 PERMISSIVE 模式开始。

    • 所有的 httpbin.full 工作负载以及在 httpbin.partial 中使用了 Sidecar 的工作负载都能够使用双向 TLS 和明文流量。

    • 命名空间 httpbin.partial 中没有 Sidecar 的服务和 httpbin.legacy 中的服务都只能使用明文流量。

    自动双向 TLS 将客户端和 sleep.full 配置为可将双向 TLS 流量发送到具有 Sidecar 的工作负载,明文流量发送到没有 Sidecar 的工作负载。

    您可以通过以下方式验证可达性:

    1. $ for from in "full" "legacy"; do for to in "full" "partial" "legacy"; do echo "sleep.${from} to httpbin.${to}";kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done; done
    2. sleep.full to httpbin.full
    3. URI=spiffe://cluster.local/ns/full/sa/sleep
    4. response code: 200
    5. sleep.full to httpbin.partial
    6. URI=spiffe://cluster.local/ns/full/sa/sleep
    7. response code: 200
    8. sleep.full to httpbin.legacy
    9. response code: 200
    10. sleep.legacy to httpbin.full
    11. response code: 200
    12. sleep.legacy to httpbin.partial
    13. response code: 200
    14. sleep.legacy to httpbin.legacy
    15. response code: 200

    无论工作负载是否带有 Sidecar,对 httpbin.partial 的请求都可以到达。Istio 自动将 sleep.full 客户端配置为使用双向 TLS 连接带有 Sidecar 的工作负载。

    1. $ for i in `seq 1 10`; do kubectl exec $(kubectl get pod -l app=sleep -n full -o jsonpath={.items..metadata.name}) -c sleep -nfull -- curl http://httpbin.partial:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done
    2. URI=spiffe://cluster.local/ns/full/sa/sleep
    3. response code: 200
    4. response code: 200
    5. URI=spiffe://cluster.local/ns/full/sa/sleep
    6. response code: 200
    7. response code: 200
    8. URI=spiffe://cluster.local/ns/full/sa/sleep
    9. response code: 200
    10. URI=spiffe://cluster.local/ns/full/sa/sleep
    11. response code: 200
    12. response code: 200
    13. URI=spiffe://cluster.local/ns/full/sa/sleep
    14. response code: 200
    15. response code: 200
    16. response code: 200

    如果不使用自动双向 TLS,您必须跟踪 Sidecar 迁移完成情况,然后显式的配置目标规则,使客户端发送双向 TLS 流量到 httpbin.full

    锁定双向 TLS 为 STRICT 模式

    您可配置认证策略为 STRICT,以锁定 httpbin.full 服务仅接收双向 TLS 流量。

    1. $ cat <<EOF | kubectl apply -n full -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. peers:

    All httpbin.full workloads and the workload with sidecar for httpbin.partial can only servemutual TLS traffic.

    所有 httpbin.full 工作负载和带有 Sidecar 的 httpbin.partial 都只可使用双向 TLS 流量。

    现在来自 sleep.legacy 的请求将开始失败,因为其不支持发送双向 TLS 流量。但是客户端 sleep.full 的请求将仍可成功返回 200 状态码,因为它已配置为自动双向 TLS,并且发送双向 TLS 请求。

    如果出于某种原因,您希望服务显式地处于明文模式,则可以将身份验证策略配置为明文。

    1. $ cat <<EOF | kubectl apply -n full -f -
    2. apiVersion: "authentication.istio.io/v1alpha1"
    3. kind: "Policy"
    4. metadata:
    5. name: "httpbin"
    6. spec:
    7. targets:
    8. - name: httpbin
    9. EOF

    在这种情况下,由于服务处于纯文本模式。Istio 自动配置客户端 Sidecar 发送明文流量以避免错误。

    1. $ for from in "full" "legacy"; do for to in "full" "partial" "legacy"; do echo "sleep.${from} to httpbin.${to}";kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done; done
    2. sleep.full to httpbin.full
    3. response code: 200
    4. sleep.full to httpbin.partial
    5. response code: 200
    6. sleep.full to httpbin.legacy
    7. response code: 200
    8. sleep.legacy to httpbin.full
    9. response code: 200
    10. sleep.legacy to httpbin.partial
    11. response code: 200
    12. sleep.legacy to httpbin.legacy
    13. response code: 200

    现在,所有流量都可以明文传输。

    重写目标规则

    例如,您可以显式的为 httpbin.full 配置目标规则,以显式启用或禁用双向 TLS。

    1. $ cat <<EOF | kubectl apply -n full -f -
    2. apiVersion: "networking.istio.io/v1alpha3"
    3. kind: "DestinationRule"
    4. metadata:
    5. name: "httpbin-full-mtls"
    6. spec:
    7. host: httpbin.full.svc.cluster.local
    8. trafficPolicy:
    9. tls:
    10. mode: ISTIO_MUTUAL
    11. EOF

    由于在前面的步骤中,我们已经禁用了 httpbin.full 的身份验证策略,以禁用双向 TLS,现在应该看到来自 sleep.full 的流量开始失败。

    1. $ for from in "full" "legacy"; do for to in "full" "partial" "legacy"; do echo "sleep.${from} to httpbin.${to}";kubectl exec $(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name}) -c sleep -n ${from} -- curl http://httpbin.${to}:8000/headers -s -w "response code: %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'; echo -n "\n"; done; done
    2. sleep.full to httpbin.full
    3. response code: 503
    4. sleep.full to httpbin.partial
    5. URI=spiffe://cluster.local/ns/full/sa/sleep
    6. response code: 200
    7. sleep.full to httpbin.legacy
    8. response code: 200
    9. sleep.legacy to httpbin.full
    10. response code: 200
    11. sleep.legacy to httpbin.partial
    12. response code: 200
    13. sleep.legacy to httpbin.legacy
    14. response code: 200
    1. $ kubectl delete ns full partial legacy

    自动双向 TLS 配置 Sidecar 客户端默认情况下在 Sidecar 之间发送 TLS 流量。您只需要配置身份验证策略。

    如前所述,自动双向 TLS 是网格 Helm 安装选项。您必须重新安装 Istio 才能启用或禁用该功能。当此功能被禁用,如果您已经依靠它来自动加密流量,则流量可以回退到纯明文模式,这可能会影响您的安全状态或中断流量(如果该服务已配置为 STRICT 模式以仅接收双向 TLS 流量)。

    当前,自动双向 TLS 还处于 Alpha 阶段,请注意其风险以及 TLS 加密的额外 CPU 成本。

    我们正在考虑将此功能设置为默认启用。当您使用自动双向 TLS 时,请考虑通过 GitHub 发送您的反馈或遇到的问题。

    Istio 2020——为了商用

    Istio 在 2020 年的愿景声明及路线图。

    一种更安全的秘密管理方式。

    DNS 证书管理

    在 Istio 中配置和管理 DNS 证书。

    Istio v1beta1 授权策略的设计原则、基本概述及迁移操作。

    安全管理 Webhook

    一种更安全管理 Istio webhook 的方法。

    将需要隔离的环境部署到单独的网格中,并通过网格联邦启用网格间通信。