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.enab...
通过这个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_TLS
,default 的流量策略也为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 Before
和Not 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
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
更多推荐
所有评论(0)