自动双向 TLS
本任务通过一个简化的工作流,展示如何使用双向 TLS。
借助 Istio 的自动双向 TLS 特性,您只需配置认证策略即可使用双向 TLS,而无需关注目标规则。
Istio 跟踪迁移到 sidecar 的服务端工作负载,并将客户端 sidecar 配置为自动向这些工作负载发送双向 TLS 流量, 同时将明文流量发送到没有 sidecar 的工作负载。这使您可以通过最少的配置,逐步在网格中使用双向 TLS。
开始之前
安装 Istio 时,配置
global.mtls.enabled
选项为 false,global.mtls.auto
选项为 true。 以安装demo
配置文件为例:
$ istioctl manifest apply --set profile=demo \
--set values.global.mtls.auto=true \
--set values.global.mtls.enabled=false
操作指南
安装
本例中,我们部署 httpbin
服务到 full
、partial
和 legacy
三个命名空间中,分别 代表 Istio 迁移的不同阶段。
命名空间 full
包含已完成 Istio 迁移的所有服务器工作负载。 每一个部署都有 Sidecar 注入。
$ kubectl create ns full
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n full
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n full
命名空间 partial
包含部分迁移到 Istio 的服务器工作负载。 只有完成迁移的服务器工作负载(由于已注入 Sidecar)能够使用双向 TLS 流量。
$ kubectl create ns partial
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n partial
$ cat <<EOF | kubectl apply -n partial -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpbin-nosidecar
spec:
replicas: 1
selector:
matchLabels:
app: httpbin
template:
metadata:
labels:
app: httpbin
version: nosidecar
spec:
containers:
- image: docker.io/kennethreitz/httpbin
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 80
EOF
命名空间 legacy
中的工作负载,都没有注入 Sidecar。
$ kubectl create ns legacy
$ kubectl apply -f @samples/httpbin/httpbin.yaml@ -n legacy
$ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy
接着,我们部署两个 sleep
工作负载,一个有 Sidecar,另一个没有。
$ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n full
$ kubectl apply -f @samples/sleep/sleep.yaml@ -n legacy
您可以确认在所有命名空间部署完成。
$ kubectl get pods -n full
$ kubectl get pods -n partial
$ kubectl get pods -n legacy
NAME READY STATUS RESTARTS AGE
httpbin-dcd949489-5cndk 2/2 Running 0 39s
sleep-58d6644d44-gb55j 2/2 Running 0 38s
NAME READY STATUS RESTARTS AGE
httpbin-6f6fc94fb6-8d62h 1/1 Running 0 10s
httpbin-dcd949489-5fsbs 2/2 Running 0 12s
NAME READY STATUS RESTARTS AGE
httpbin-54f5bb4957-lzxlg 1/1 Running 0 6s
sleep-74564b477b-vb6h4 1/1 Running 0 4s
您还需验证系统中是否存在默认的网格验证策略,可以参考下面操作:
$ kubectl get policies.authentication.istio.io --all-namespaces
$ kubectl get meshpolicies -o yaml | grep ' mode'
NAMESPACE NAME AGE
istio-system grafana-ports-mtls-disabled 2h
mode: PERMISSIVE
最后但并非最不重要的一点是,确认没有应用于示例服务的目标规则。 您可以通过检查已有目标规则的 host:
字段,并确保它们没有匹配我们的示例服务。例如:
$ kubectl get destinationrules.networking.istio.io --all-namespaces -o yaml | grep "host:"
host: istio-policy.istio-system.svc.cluster.local
host: istio-telemetry.istio-system.svc.cluster.local
您可通过使用 curl
从命名空间 full
、partial
或 legacy
中的任一 sleep
Pod 发送 HTTP 请求到 httpbin.full
、httpbin.partial
或 httpbin.legacy
以验证安装。 所有的请求都应成功返回 HTTP 200 状态码。
例如,这是一个检查 sleep.full
到 httpbin.full
可达性的命令:
$ kubectl exec $(kubectl get pod -l app=sleep -n full -o jsonpath={.items..metadata.name}) -c sleep -n full -- curl http://httpbin.full:8000/headers -s -w "response %{http_code}\n" | egrep -o 'URI\=spiffe.*sa/[a-z]*|response.*$'
URI=spiffe://cluster.local/ns/full/sa/sleep
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 的工作负载。
您可以通过以下方式验证可达性:
$ 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
sleep.full to httpbin.full
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
sleep.full to httpbin.partial
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
sleep.full to httpbin.legacy
response code: 200
sleep.legacy to httpbin.full
response code: 200
sleep.legacy to httpbin.partial
response code: 200
sleep.legacy to httpbin.legacy
response code: 200
使用 Sidecar 迁移
无论工作负载是否带有 Sidecar,对 httpbin.partial
的请求都可以到达。 Istio 自动将 sleep.full
客户端配置为使用双向 TLS 连接带有 Sidecar 的工作负载。
$ 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
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
response code: 200
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
response code: 200
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
response code: 200
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
response code: 200
response code: 200
如果不使用自动双向 TLS,您必须跟踪 Sidecar 迁移完成情况,然后显式的配置目标规则,使客户端发送双向 TLS 流量到 httpbin.full
。
锁定双向 TLS 为 STRICT 模式
您可配置认证策略为 STRICT
,以锁定 httpbin.full
服务仅接收双向 TLS 流量。
$ cat <<EOF | kubectl apply -n full -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "httpbin"
spec:
targets:
- name: httpbin
peers:
- mtls: {}
EOF
All httpbin.full
workloads and the workload with sidecar for httpbin.partial
can only serve mutual TLS traffic.
所有 httpbin.full
工作负载和带有 Sidecar 的 httpbin.partial
都只可使用双向 TLS 流量。
现在来自 sleep.legacy
的请求将开始失败,因为其不支持发送双向 TLS 流量。 但是客户端 sleep.full
的请求将仍可成功返回 200 状态码,因为它已配置为自动双向 TLS,并且发送双向 TLS 请求。
$ 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
sleep.full to httpbin.full
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
sleep.full to httpbin.partial
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
sleep.full to httpbin.legacy
response code: 200
sleep.legacy to httpbin.full
response code: 000
command terminated with exit code 56
sleep.legacy to httpbin.partial
response code: 200
sleep.legacy to httpbin.legacy
response code: 200
禁用双向 TLS 以启用明文传输
如果出于某种原因,您希望服务显式地处于明文模式,则可以将身份验证策略配置为明文。
$ cat <<EOF | kubectl apply -n full -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "httpbin"
spec:
targets:
- name: httpbin
EOF
在这种情况下,由于服务处于纯文本模式。Istio 自动配置客户端 Sidecar 发送明文流量以避免错误。
$ 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
sleep.full to httpbin.full
response code: 200
sleep.full to httpbin.partial
response code: 200
sleep.full to httpbin.legacy
response code: 200
sleep.legacy to httpbin.full
response code: 200
sleep.legacy to httpbin.partial
response code: 200
sleep.legacy to httpbin.legacy
response code: 200
现在,所有流量都可以明文传输。
重写目标规则
为了向后兼容,您仍然可以像以前一样使用目标规则来覆盖 TLS 配置。当目标规则具有显式 TLS 配置时,它将覆盖 Sidecar 客户端的 TLS 配置。
例如,您可以显式的为 httpbin.full
配置目标规则,以显式启用或禁用双向 TLS。
$ cat <<EOF | kubectl apply -n full -f -
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "httpbin-full-mtls"
spec:
host: httpbin.full.svc.cluster.local
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
EOF
由于在前面的步骤中,我们已经禁用了 httpbin.full
的身份验证策略,以禁用双向 TLS,现在应该看到来自 sleep.full
的流量开始失败。
$ 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
sleep.full to httpbin.full
response code: 503
sleep.full to httpbin.partial
URI=spiffe://cluster.local/ns/full/sa/sleep
response code: 200
sleep.full to httpbin.legacy
response code: 200
sleep.legacy to httpbin.full
response code: 200
sleep.legacy to httpbin.partial
response code: 200
sleep.legacy to httpbin.legacy
response code: 200
清理
$ kubectl delete ns full partial legacy
摘要
自动双向 TLS 配置 Sidecar 客户端默认情况下在 Sidecar 之间发送 TLS 流量。您只需要配置身份验证策略。
如前所述,自动双向 TLS 是网格 Helm 安装选项。您必须重新安装 Istio 才能启用或禁用该功能。 当此功能被禁用,如果您已经依靠它来自动加密流量,则流量可以回退到纯明文模式, 这可能会影响您的安全状态或中断流量(如果该服务已配置为 STRICT
模式以仅接收双向 TLS 流量)。
当前,自动双向 TLS 还处于 Alpha 阶段,请注意其风险以及 TLS 加密的额外 CPU 成本。
我们正在考虑将此功能设置为默认启用。当您使用自动双向 TLS 时,请考虑通过 GitHub 发送您的反馈或遇到的问题。
相关内容
Istio 在 2020 年的愿景声明及路线图。
一种更安全的秘密管理方式。
在 Istio 中配置和管理 DNS 证书。
Istio v1beta1 授权策略的设计原则、基本概述及迁移操作。
一种更安全管理 Istio webhook 的方法。
将需要隔离的环境部署到单独的网格中,并通过网格联邦启用网格间通信。