Peer Authentication Policy使用要点测试案例
准备基础环境
01-demoapp-v10
[root@k8s-master ms-demo]# cat 01-demoapp-v10/deploy-demoapp.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: demoappv10
version: v1.0
name: demoappv10
spec:
progressDeadlineSeconds: 600
replicas: 3
selector:
matchLabels:
app: demoapp
version: v1.0
template:
metadata:
labels:
app: demoapp
version: v1.0
spec:
containers:
- image: ikubernetes/demoapp:v1.0
imagePullPolicy: IfNotPresent
name: demoapp
env:
- name: "PORT"
value: "8080"
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
limits:
cpu: 50m
---
apiVersion: v1
kind: Service
metadata:
name: demoappv10
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: demoapp
version: v1.0
type: ClusterIP
---
[root@k8s-master ms-demo]# cat 01-demoapp-v10/deploy-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy
spec:
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- env:
- name: PROXYURL
value: http://demoappv10:8080
image: ikubernetes/proxy:v0.1.1
imagePullPolicy: IfNotPresent
name: proxy
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
limits:
cpu: 50m
---
apiVersion: v1
kind: Service
metadata:
name: proxy
spec:
ports:
- name: http-80
port: 80
protocol: TCP
targetPort: 8080
selector:
app: proxy
---
02-demoapp-v11
[root@k8s-master ms-demo]# cat 02-demoapp-v11/deploy-demoapp-v11.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: demoappv11
version: v1.1
name: demoappv11
spec:
progressDeadlineSeconds: 600
replicas: 2
selector:
matchLabels:
app: demoapp
version: v1.1
template:
metadata:
labels:
app: demoapp
version: v1.1
spec:
containers:
- image: ikubernetes/demoapp:v1.1
imagePullPolicy: IfNotPresent
name: demoapp
env:
- name: "PORT"
value: "8080"
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
limits:
cpu: 50m
---
apiVersion: v1
kind: Service
metadata:
name: demoappv11
spec:
ports:
- name: http-8080
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: demoapp
version: v1.1
type: ClusterIP
---
[root@k8s-master ms-demo]# cat 02-demoapp-v11/service-demoapp.yaml
---
apiVersion: v1
kind: Service
metadata:
name: demoapp
spec:
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: demoapp
type: ClusterIP
---
[root@k8s-master ms-demo]# cat 02-demoapp-v11/deploy-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: proxy
spec:
progressDeadlineSeconds: 600
replicas: 1
selector:
matchLabels:
app: proxy
template:
metadata:
labels:
app: proxy
spec:
containers:
- env:
- name: PROXYURL
value: http://demoapp:8080
image: ikubernetes/proxy:v0.1.1
imagePullPolicy: IfNotPresent
name: proxy
ports:
- containerPort: 8080
name: web
protocol: TCP
resources:
limits:
cpu: 50m
---
apiVersion: v1
kind: Service
metadata:
name: proxy
spec:
ports:
- name: http-80
port: 80
protocol: TCP
targetPort: 8080
selector:
app: proxy
---
[root@k8s-master ms-demo]# cat 02-demoapp-v11/virutalservice-demoapp.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: demoapp
spec:
hosts:
- demoapp
http:
- name: canary
match:
- uri:
prefix: /canary
rewrite:
uri: /
route:
- destination:
host: demoappv11
- name: default
route:
- destination:
host: demoappv10
03-demoapp-subset
[root@k8s-master ms-demo]# cat 03-demoapp-subset/destinationrule-demoapp.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
subsets:
- name: v10
labels:
version: v1.0
- name: v11
labels:
version: v1.1
[root@k8s-master ms-demo]# cat 03-demoapp-subset/virutalservice-demoapp.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: demoapp
spec:
hosts:
- demoapp
http:
- name: canary
match:
- uri:
prefix: /canary
rewrite:
uri: /
route:
- destination:
host: demoapp
subset: v11
- name: default
route:
- destination:
host: demoapp
subset: v10
04-proxy-gateway
[root@k8s-master ms-demo]# cat 04-proxy-gateway/gateway-proxy.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: proxy-gateway
namespace: istio-system # 要指定为ingress gateway pod所在名称空间
spec:
selector:
app: istio-ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "fe.yzy.com"
[root@k8s-master ms-demo]# cat 04-proxy-gateway/virtualservice-proxy.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: proxy
spec:
hosts:
- "fe.yzy.com" # 对应于gateways/proxy-gateway
gateways:
- istio-system/proxy-gateway # 相关定义仅应用于Ingress Gateway上
#- mesh
http:
- name: default
route:
- destination:
host: proxy
kubectl apply -f ./01-demoapp-v10
kubectl apply -f ./02-demoapp-v11
kubectl apply -f ./03-demoapp-subset
kubectl delete svc demoappv10 demoappv11
kubectl apply -f ./04-proxy-gateway
创建PA,模式为PERMISSIVE
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f 01-namespace-default-peerauthn.yaml
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 01-namespace-default-peerauthn.yaml
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: PERMISSIVE
---
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl get pa
NAME MODE AGE
default PERMISSIVE 3s
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f /root/istio-1.14.1/samples/sleep/sleep.yaml
看下sleep在哪个node上,然后去该node进行tcp抓包,我的是在node2上
[root@k8s-master sleep]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demoappv10-b5d9576cc-54jxx 2/2 Running 0 51m 10.244.36.90 k8s-node1 <none> <none>
demoappv10-b5d9576cc-5hx8d 2/2 Running 0 51m 10.244.169.148 k8s-node2 <none> <none>
demoappv10-b5d9576cc-f6fpb 2/2 Running 0 51m 10.244.169.154 k8s-node2 <none> <none>
demoappv11-77755cdc65-2xz4d 2/2 Running 0 50m 10.244.36.78 k8s-node1 <none> <none>
demoappv11-77755cdc65-6prmq 2/2 Running 0 50m 10.244.169.145 k8s-node2 <none> <none>
proxy-7f9c9ffff5-2kcd6 2/2 Running 0 50m 10.244.169.156 k8s-node2 <none> <none>
sleep-698cfc4445-p84t6 2/2 Running 0 17m 10.244.169.151 k8s-node2 <none> <none>
sleep的ip是10.244.169.151匹配的接口是cali52787c1ffa8
[root@k8s-node2 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.211.55.1 0.0.0.0 UG 100 0 0 eth0
10.211.55.0 0.0.0.0 255.255.255.0 U 100 0 0 eth0
10.244.36.64 10.211.55.21 255.255.255.192 UG 0 0 0 tunl0
10.244.169.128 0.0.0.0 255.255.255.192 U 0 0 0 *
10.244.169.145 0.0.0.0 255.255.255.255 UH 0 0 0 califb18e2b98c0
10.244.169.148 0.0.0.0 255.255.255.255 UH 0 0 0 calia109ade752f
10.244.169.151 0.0.0.0 255.255.255.255 UH 0 0 0 cali52787c1ffa8
10.244.169.154 0.0.0.0 255.255.255.255 UH 0 0 0 cali4a7d42ee79a
10.244.169.156 0.0.0.0 255.255.255.255 UH 0 0 0 cali214f50b2299
10.244.235.192 10.211.55.20 255.255.255.192 UG 0 0 0 tunl0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
直接抓cali52787c1ffa8接口8080端口
[root@k8s-node2 ~]# tcpdump -i cali52787c1ffa8 -nn -X tcp port 8080
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl exec -it sleep-698cfc4445-p84t6 -- /bin/sh
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-5hx8d, ServerIP: 10.244.169.148!
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-f6fpb, ServerIP: 10.244.169.154!
查看抓包结果内容是加密的,就可以证明如果客户端和服务端都支持双向TLS通信,双方建立的就是双向TLS通信。
在demo namespace下创建一个pods,查看一下client运行的node节点
[root@k8s-master ~]# kubectl create ns demo
[root@k8s-master ~]# kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 -it --restart=Never -n demo --command -- /bin/sh
root@client-10058 # curl demoapp.default:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-f6fpb, ServerIP: 10.244.169.154!
[root@k8s-master sleep]# kubectl get pods -o wide -n demo
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
client-10058 1/1 Running 0 4m22s 10.244.169.157 k8s-node2 <none> <none>
用client再次访问demoapp.default:8080,然后抓包
[root@k8s-node2 ~]# tcpdump -i cali79b091049f0 -nn -X tcp port 8080
可以看到这个抓包结果是明文的,已经可以看到HTTP的一些访问信息
通过上面的实验就证明如果服务端定义的策略是PERMISSIVE,只要客户端无论支持不支持都能与服务端进行通信,如果支持建立起来的就是mTLS通信,如果不支持就是明文通信。
创建一个mode为STRICT模式的PA
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f 02-demoapp-peerauthn.yaml
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 02-demoapp-peerauthn.yaml
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: demoapp
namespace: default
spec:
selector:
matchLabels:
app: demoapp
mtls:
mode: STRICT
---
在sleep上curl访问
[root@k8s-master ~]# kubectl exec -it sleep-698cfc4445-p84t6 -- /bin/sh
/ $
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-5hx8d, ServerIP: 10.244.169.148!
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-f6fpb, ServerIP: 10.244.169.154!
/ $
抓包结果可以看出也还是加密的
使用client访问demoapp,可以看到是拒绝的
原因是因为服务端必须要求建立TLS通信,而客户端不支持,所以会被拒绝掉
[root@k8s-master ~]# kubectl run client-$RANDOM --image=ikubernetes/admin-box:v1.2 -it --restart=Never -n demo --command -- /bin/sh
root@client-10058 # curl demoapp.default:8080
curl: (56) Recv failure: Connection reset by peer
客户端禁止使用TLS通信
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f 03-destinationrule-demoapp-mtls.yaml
destinationrule.networking.istio.io/demoapp configured
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 03-destinationrule-demoapp-mtls.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
tls:
mode: DISABLE
subsets:
- name: v10
labels:
version: v1.0
- name: v11
labels:
version: v1.1
继续用sleep访问demoapp
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-f6fpb, ServerIP: 10.244.169.154!
/ $
查看抓包结果
tcpdump -icali52787c1ffa8 -nn -X tcp port 8080
创建客户端要求通信必须为TLS
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f 03-destinationrule-demoapp-mtls.yaml
destinationrule.networking.istio.io/demoapp configured
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 03-destinationrule-demoapp-mtls.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
tls:
mode: ISTIO_MUTUAL
subsets:
- name: v10
labels:
version: v1.0
- name: v11
labels:
version: v1.1
/ $ curl demoapp:8080
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.6, ServerName: demoappv10-b5d9576cc-54jxx, ServerIP: 10.244.36.90!
/ $
将服务端TLS加密关掉
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# kubectl apply -f 01-namespace-default-peerauthn.yaml
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 01-namespace-default-peerauthn.yaml
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: DISABLE
---
使用客户端访问,可以看到是访问失败的。
是因为客户端必须要求加密,服务不支持加密
修改为PERMISSIVE又可以继续通信了
[root@k8s-master 01-PeerAuthentication-Policy-Basics]# cat 01-namespace-default-peerauthn.yaml
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
namespace: default
spec:
mtls:
mode: PERMISSIVE
---
将模式改为SIMPLE
[root@master 01-PeerAuthentication-Policy-Basics]# cat 03-destinationrule-demoapp-mtls.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: demoapp
spec:
host: demoapp
trafficPolicy:
loadBalancer:
simple: LEAST_CONN
tls:
mode: SIMPLE
subsets:
- name: v10
labels:
version: v1.0
- name: v11
labels:
version: v1.1
再次访问发现被拒绝掉了,是因为SIMPLE模式不会使用Istio发过来的证书