[zh] sync /security/authorization/authz-tcp/ (#12906)

This commit is contained in:
Michael 2023-03-19 11:40:41 +08:00 committed by GitHub
parent 19431056ba
commit ec982f6091
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 35 deletions

View File

@ -19,11 +19,11 @@ test: yes
* 按照 [Istio 安装指南](/zh/docs/setup/install/istioctl/)安装 Istio。
* 在命名空间例如 `foo` 中部署两个工作负载`sleep` 和 `tcp-echo`
* 在命名空间例如 `foo` 中部署两个工作负载`sleep` 和 `tcp-echo`
这两个工作负载每个前面都会运行一个 Envoy 代理。
`tcp-echo` 工作负载会监听端口 9000、9001 和 9002并以前缀 `hello` 输出它收到的所有流量。
例如,如果您发送 "world" 给 `tcp-echo`,那么它将会回复 `hello world`
`tcp-echo` 的 Kubernetes 服务对象只声明了端口 9000 和 9001而省略了端口 9002。直通过滤器链将处理端口 9002 的流量。
`tcp-echo` 的 Kubernetes 服务对象只声明了端口 9000 和 9001而省略了端口 9002。透传过滤器链将处理端口 9002 的流量。
使用以下命令部署示例命名空间和工作负载:
{{< text bash >}}
@ -35,13 +35,17 @@ test: yes
* 使用以下命令确认 `sleep` 可以成功与 `tcp-echo` 的端口 9000 和 9001 交互:
{{< text bash >}}
$ 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 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9000
connection succeeded
{{< /text >}}
{{< text bash >}}
$ 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'
$ 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'
hello port 9001
connection succeeded
{{< /text >}}
@ -52,7 +56,9 @@ test: yes
{{< text bash >}}
$ 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'
$ 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'
hello port 9002
connection succeeded
{{< /text >}}
@ -88,7 +94,9 @@ test: yes
1. 使用以下命令验证是否允许请求端口 9000
{{< text bash >}}
$ 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 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
hello port 9000
connection succeeded
{{< /text >}}
@ -96,15 +104,20 @@ test: yes
1. 使用以下命令验证是否允许请求端口 9001
{{< text bash >}}
$ 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'
$ 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'
hello port 9001
connection succeeded
{{< /text >}}
1. 验证对端口 9002 的请求是否被拒绝。即使未在 `tcp-echo` Kubernetes 服务对象中显式声明的端口,授权策略也将其应用于直通过滤器链。运行以下命令并验证输出:
1. 验证对端口 9002 的请求是否被拒绝。即使未在 `tcp-echo` Kubernetes 服务对象中显式声明的端口,
授权策略也将其应用于透传过滤器链。运行以下命令并验证输出:
{{< text bash >}}
$ 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'
$ 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'
connection rejected
{{< /text >}}
@ -135,14 +148,18 @@ test: yes
运行以下命令并验证输出:
{{< text bash >}}
$ 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 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
{{< /text >}}
1. 验证对端口 9001 的请求是否被拒绝。发生这种情况是因为请求与任何 ALLOW 规则都不匹配。运行以下命令并验证输出:
{{< text bash >}}
$ 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'
$ 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'
connection rejected
{{< /text >}}
@ -169,17 +186,22 @@ test: yes
EOF
{{< /text >}}
1. 验证到 port 9000 的请求是否被拒绝。发生这种情况是因为 Istio 在为 tcp 端口创建 DENY 规则时不理解 HTTP-only 字段,并且由于这个规则的限制性质,将拒绝所有到 tcp 端口的流量:
1. 验证到 port 9000 的请求是否被拒绝。发生这种情况是因为 Istio 在为 tcp 端口创建 DENY
规则时不理解 HTTP-only 字段,并且由于这个规则的限制性质,将拒绝所有到 tcp 端口的流量:
{{< text bash >}}
$ 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 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
{{< /text >}}
1. 验证到 port 9001 的请求是否被拒绝。原因同上。
{{< text bash >}}
$ 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'
$ 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'
connection rejected
{{< /text >}}
@ -208,14 +230,18 @@ test: yes
1. 验证对端口 9000 的请求是否被拒绝。发生这种情况是因为此类请求与上述 DENY 策略中的 `ports` 匹配。
{{< text bash >}}
$ 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 9000" | nc tcp-echo 9000' | grep "hello" && echo 'connection succeeded' || echo 'connection rejected'
connection rejected
{{< /text >}}
1. 验证是否允许对端口 9001 的请求。发生这种情况是因为请求与 DENY 策略中的 `ports` 不匹配:
{{< text bash >}}
$ 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'
$ 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'
hello port 9001
connection succeeded
{{< /text >}}

View File

@ -14,20 +14,22 @@ status: Experimental
这个特性需要 Kubernetes 版本 >= 1.18。
此任务演示如何提供工作负载证书的自定义证书颁发机构 [Kubernetes CSR API](https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests/)。
不同的工作负载可以获取不同的证书签名者签名的证书。每个证书签名者本质上是一个不同的 CA。
可以预期的是,如果工作负载的证书是同一个证书签名者颁发的,则这些工作负载可以与 MTLS 通信,而不同签名者签名的工作负载则不能这样。
这个特性利用了 [Chiron](/zh/blog/2019/dns-cert/),一个与 Istiod 关联的轻量级组件,使用 Kubernetes CSR API 签署证书。
此任务演示如何使用集成了
[Kubernetes CSR API](https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests/)
的自定义证书颁发机构来制备工作负载证书。不同的工作负载可以获取不同的证书签名者签名的证书。
每个证书签名者本质上是一个不同的 CA。可以预期的是如果工作负载的证书是同一个证书签名者颁发的
则这些工作负载可以与 MTLS 通信,而不同签名者签名的工作负载则不能这样。这个特性利用了
[Chiron](/zh/blog/2019/dns-cert/),这是一个与 Istiod 关联的轻量级组件,使用 Kubernetes CSR API 签署证书。
在本例中,我们使用[开源 cert-manager](https://cert-manager.io)。
Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigningRequests` 实验性支持](https://cert-manager.io/docs/usage/kube-csr/)。
在本例中,我们使用[开源 cert-manager](https://cert-manager.io)。Cert-manager 从 1.4
版本开始已增加了[对 Kubernetes `CertificateSigningRequests` 实验性支持](https://cert-manager.io/docs/usage/kube-csr/)。
## 在 Kubernetes 集群中部署自定义 CA 控制器{#deploy-custom-ca-controller-in-the-k8s-cluster}
1. 按照[安装文档](https://cert-manager.io/docs/installation/)部署 cert-manager。
{{< warning >}}
注:确保启用特性门控`--feature-gates=ExperimentalCertificateSigningRequestControllers=true`
确保启用特性门控 `--feature-gates=ExperimentalCertificateSigningRequestControllers=true`
{{< /warning >}}
1. 为 cert-manager 创建三个自签名的集群签发器:`istio-system`、`foo` 和 `bar`
@ -127,13 +129,11 @@ Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigning
## 导出每个集群签发器的根证书{#export-root-certificates-for-each-cluster-issuer}
{{< text bash >}}
$ export istioca=$(kubectl get clusterissuers istio-system -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
$ export fooca=$(kubectl get clusterissuers foo -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
$ export barca=$(kubectl get clusterissuers bar -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
{{< /text >}}
{{< text bash >}}
$ export istioca=$(kubectl get clusterissuers istio-system -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
$ export fooca=$(kubectl get clusterissuers foo -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
$ export barca=$(kubectl get clusterissuers bar -o jsonpath='{.spec.ca.secretName}' | xargs kubectl get secret -n cert-manager -o jsonpath='{.data.ca\.crt}' | base64 -d)
{{< /text >}}
## 使用默认的证书签名者信息部署 Istio{#deploy-istio-with-default-cert-signer-info}
@ -238,7 +238,6 @@ Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigning
$ kubectl apply -f samples/httpbin/httpbin.yaml -n foo
$ kubectl apply -f samples/sleep/sleep.yaml -n foo
$ kubectl apply -f samples/httpbin/httpbin.yaml -n bar
$ kubectl apply -f samples/sleep/sleep.yaml -n bar
{{< /text >}}
## 验证相同命名空间内 `httpbin``sleep` 之间的网络连通性{#verify-network-connectivity-between-httpbin-and-sleep-within-a-namespace}
@ -248,10 +247,15 @@ Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigning
`bar` 命名空间下的工作负载将使用 `bar` 集群签发器。要验证它们已经被正确的集群签发器进行了真正的签名,
我们可以验证相同命名空间下的工作负载可以通信,而不同命名空间下的工作负载不能通信。
1. 检查 `foo` 命名空间中 `sleep``httpbin` 服务之间的网络连通性
1. `SLEEP_POD_FOO` 环境变量设置为 `sleep` Pod 的名称
{{< text bash >}}
$ export SLEEP_POD_FOO=$(kubectl get pod -n foo -l app=sleep -o jsonpath={.items..metadata.name})
{{< /text >}}
1. 检查 `foo` 命名空间中 `sleep``httpbin` 服务之间的网络连通性。
{{< text bash >}}
$ kubectl exec -it $SLEEP_POD_FOO -n foo -c sleep curl http://httpbin.foo:8000/html
<!DOCTYPE html>
<html>
@ -271,7 +275,6 @@ Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigning
1. 检查 `foo` 命名空间中的 `sleep` 服务与 `bar` 命名空间中的 `httpbin` 服务之间的网络连通性。
{{< text bash >}}
$ export SLEEP_POD_FOO=$(kubectl get pod -n foo -l app=sleep -o jsonpath={.items..metadata.name})
$ kubectl exec -it $SLEEP_POD_FOO -n foo -c sleep curl http://httpbin.bar:8000/html
upstream connect error or disconnect/reset before headers. reset reason: connection failure, transport failure reason: TLS error: 268435581:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED
{{< /text >}}
@ -286,8 +289,10 @@ Cert-manager 从 1.4 版本开始已增加了[对 Kubernetes `CertificateSigning
$ kubectl delete ns bar
{{< /text >}}
## 使用此功能的原因{#reasons-to-use-this-feature}
## 使用此特性的原因{#reasons-to-use-this-feature}
* 自定义 CA 集成 - 通过在 Kubernetes CSR 请求中指定签名者名称,此功能允许 Istio 使用 Kubernetes CSR API 接口与自定义证书颁发机构集成。这确实需要自定义 CA 来实现一个 Kubernetes 控制器来观察 `CertificateSigningRequest``Certificate` 资源并对其采取行动。
* 自定义 CA 集成 - 通过在 Kubernetes CSR 请求中指定签名者名称,此特性允许 Istio 使用 Kubernetes CSR API
接口与自定义证书颁发机构集成。这确实需要自定义 CA 来实现一个 Kubernetes 控制器来观察
`CertificateSigningRequest``Certificate` 资源并对其采取行动。
* 更好的多租户 - 通过为不同工作负载指定不同的证书签名者,不同租户的工作负载所用的证书可以由不同的 CA 进行签名。