1. 准备工作
将两个名为sleep和tcp-echo的工作负载一起部署到一个名称空间中,例如foo。这两个工作负载都在前面有一个enovy代理。tcp-echo工作负载在端口9000、9001和9002上进行侦听,并回送它收到的带有前缀hello的任何通信量。例如,如果您将“world”发送到tcp-echo,它将回复hello world。tcp-echo Kubernetes服务对象只声明了端口9000和9001,而忽略了端口9002。一个直通过滤器链将处理端口9002流量。使用以下命令部署示例名称空间和工作负载:
$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f samples/tcp-echo/tcp-echo.yaml) -n foo
$ kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml) -n foo
- 校验sleep成功和
tcp-echo
端口的9000,9001成功通信,使用如下命令
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 校验sleep成功和
tcp-echo
端口的9002通信。
TCP_ECHO_IP=$(kubectl get pod "$(kubectl get pod -l app=tcp-echo -n foo -o jsonpath={.items..metadata.name})" -n foo -o jsonpath="{.status.podIP}")
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
2. 配置针对TCP工作流的访问控制
- 在foo名称空间中为tcp-echo工作负载创建tcp-policy授权策略。运行以下命令应用策略,以允许请求到端口9000和9001:
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: tcp-policy
namespace: foo
spec:
selector:
matchLabels:
app: tcp-echo
action: ALLOW
rules:
- to:
- operation:
ports: ["9000", "9001"]
EOF
- 校验请求9000的端口是允许的
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 校验请求的9001端口是允许的
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 校验到9002端口的请求是拒绝的。 这是由授权策略实施的,该策略也适用于pass - through过滤器链,即使端口没有在tcp-echo Kubernetes服务对象中显式声明。运行以下命令并验证输出:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c "echo \"port 9002\" | nc $TCP_ECHO_IP 9002" | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 更新添加的策略,去添加一个
HTTP-only
字段,命名为methods
,端口号为9000.
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: tcp-policy
namespace: foo
spec:
selector:
matchLabels:
app: tcp-echo
action: ALLOW
rules:
- to:
- operation:
methods: ["GET"]
ports: ["9000"]
EOF
- 验证对端口9000的请求被拒绝。发生这种情况是因为当规则为TCP通信使用一个只支持http的字段(方法)时,该规则变得无效。Istio忽略无效的允许规则。最后的结果是请求被拒绝,因为它不匹配任何允许规则。运行以下命令并验证输出
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 校验请求到9001端口为拒绝。 这是因为请求不匹配任何允许规则。运行以下命令并验证输出:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 使用如下命令更新策略为DENY
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: tcp-policy
namespace: foo
spec:
selector:
matchLabels:
app: tcp-echo
action: DENY
rules:
- to:
- operation:
methods: ["GET"]
ports: ["9000"]
EOF
- 验证对端口9000的请求被拒绝。出现这种情况是因为Istio在一个无效的DENY规则中忽略了只支持http的字段。这与无效的ALLOW规则不同,后者会导致Istio忽略整个规则。最后的结果是只有ports字段被Istio使用,请求被拒绝,因为它们与端口匹配:
$ kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
- 校验请求到9001端口是允许的,在拒绝策略中因为请求不匹配
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- sh -c 'echo "port 9001" | nc tcp-echo 9001' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
3. 清除本小节实验
$ kubectl delete namespace foo