mirror of https://github.com/istio/istio.io.git
[zh] improve authz-ingress authz-jwt authz-td-migration (#13065)
Signed-off-by: xin.li <xin.li@daocloud.io>
This commit is contained in:
parent
1745469e9e
commit
545dc341b5
|
@ -17,7 +17,8 @@ test: yes
|
|||
|
||||
* 使用 [Istio 安装指南](/zh/docs/setup/install/istioctl/)安装 Istio。
|
||||
|
||||
* 在命名空间中部署工作负载 `httpbin`,例如 `foo`,并使用以下命令通过 Istio 入口网关公开它:
|
||||
* 在命名空间中部署工作负载 `httpbin`,例如 `foo`,并使用以下命令通过 Istio
|
||||
入口网关公开它:
|
||||
|
||||
{{< text bash >}}
|
||||
$ kubectl create ns foo
|
||||
|
@ -31,7 +32,8 @@ test: yes
|
|||
$ kubectl get pods -n istio-system -o name -l istio=ingressgateway | sed 's|pod/||' | while read -r pod; do istioctl proxy-config log "$pod" -n istio-system --level rbac:debug; done
|
||||
{{< /text >}}
|
||||
|
||||
* 遵从[确定入口 IP 和端口](/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports)中的指示说明来定义 `INGRESS_HOST` 和 `INGRESS_PORT` 环境变量。
|
||||
* 遵从[确定入口 IP 和端口](/zh/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports)中的指示说明来定义
|
||||
`INGRESS_HOST` 和 `INGRESS_PORT` 环境变量。
|
||||
|
||||
* 使用以下命令验证 `httpbin` 工作负载和入口网关正在按预期工作:
|
||||
|
||||
|
@ -46,23 +48,38 @@ test: yes
|
|||
|
||||
## 将流量引入 Kubernetes 和 Istio {#getting-traffic-into-Kubernetes-and-Istio}
|
||||
|
||||
所有将流量引入 Kubernetes 的方法都涉及在所有工作节点上打开一个端口,实现这一点的主要功能是 `NodePort` 服务和 `LoadBalancer` 服务,甚至 Kubernetes 的 `Ingress` 资源也必须由 Ingress 控制器支持,该控制器将创建 `NodePort` 或 `LoadBalancer` 服务。
|
||||
所有将流量引入 Kubernetes 的方法都涉及在所有工作节点上打开一个端口,
|
||||
实现这一点的主要功能是 `NodePort` 服务和 `LoadBalancer` 服务,甚至
|
||||
Kubernetes 的 `Ingress` 资源也必须由 Ingress 控制器支持,该控制器将创建
|
||||
`NodePort` 或 `LoadBalancer` 服务。
|
||||
|
||||
* `NodePort` 只是在每个工作节点上打开一个 30000-32767 范围内的端口,并使用标签选择器来识别将流量发送到哪些 Pod。您必须在工作节点前面手动创建某种负载均衡器或使用轮询模式的 DNS。
|
||||
* `NodePort` 只是在每个工作节点上打开一个 30000-32767 范围内的端口,
|
||||
并使用标签选择器来识别将流量发送到哪些 Pod。
|
||||
您必须在工作节点前面手动创建某种负载均衡器或使用轮询模式的 DNS。
|
||||
|
||||
* `LoadBalancer` 就像 `NodePort` 一样,除了它还创建一个特定于环境的外部负载均衡器来处理将流量分配到工作节点。例如,在 AWS EKS 中,`LoadBalancer` 服务将创建一个以您的工作程序节点为目标的经典 ELB。如果您的 Kubernetes 环境没有 `LoadBalancer` 实现,那么它的行为就像 `NodePort`。Istio 入口网关创建一个 `LoadBalancer`服务。
|
||||
* `LoadBalancer` 就像 `NodePort` 一样,
|
||||
除了它还创建一个特定于环境的外部负载均衡器来处理将流量分配到工作节点。
|
||||
例如,在 AWS EKS 中,`LoadBalancer` 服务将创建一个以您的工作程序节点为目标的经典
|
||||
ELB。如果您的 Kubernetes 环境没有 `LoadBalancer` 实现,那么它的行为就像
|
||||
`NodePort`。Istio 入口网关创建一个 `LoadBalancer`服务。
|
||||
|
||||
如果处理来自 `NodePort` 或 `LoadBalancer` 的流量的 Pod 没有在接收流量的工作节点上运行怎么办?Kubernetes 有自己的内部代理,称为 kube-proxy,用于接收数据包并将数据包转发到正确的节点。
|
||||
如果处理来自 `NodePort` 或 `LoadBalancer` 的流量的 Pod
|
||||
没有在接收流量的工作节点上运行怎么办?Kubernetes 有自己的内部代理,
|
||||
称为 kube-proxy,用于接收数据包并将数据包转发到正确的节点。
|
||||
|
||||
## 原始客户端的源 IP 地址 {#source-ip-address-of-the-original-client}
|
||||
|
||||
如果数据包通过外部代理负载均衡器和/或 kube-proxy,则客户端的原始源 IP 地址会丢失。以下是一些保留原始客户端 IP 以用于日志记录或安全目的的策略。
|
||||
如果数据包通过外部代理负载均衡器和/或 kube-proxy,则客户端的原始源 IP
|
||||
地址会丢失。以下是一些保留原始客户端 IP 以用于日志记录或安全目的的策略。
|
||||
|
||||
{{< tabset category-name="lb" >}}
|
||||
|
||||
{{< tab name="TCP/UDP 代理负载均衡器" category-value="proxy" >}}
|
||||
|
||||
如果您使用的是 TCP/UDP 代理外部负载均衡器(AWS Classic ELB),它可以使用[代理协议](https://www.haproxy.com/blog/haproxy/proxy-protocol/)嵌入原始数据包数据中的客户端 IP 地址。外部负载均衡器和 Istio 入口网关都必须支持代理协议才能工作。在 Istio 中,您可以使用 `EnvoyFilter` 启用它,如下所示:
|
||||
如果您使用的是 TCP/UDP 代理外部负载均衡器(AWS Classic ELB),
|
||||
它可以使用[代理协议](https://www.haproxy.com/blog/haproxy/proxy-protocol/)嵌入原始数据包数据中的客户端
|
||||
IP 地址。外部负载均衡器和 Istio 入口网关都必须支持代理协议才能工作。在 Istio 中,
|
||||
您可以使用 `EnvoyFilter` 启用它,如下所示:
|
||||
|
||||
{{< text yaml >}}
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
|
@ -122,8 +139,12 @@ spec:
|
|||
|
||||
{{< tab name="Network Load Balancer" category-value="network" >}}
|
||||
|
||||
如果您使用的是保留客户端 IP 地址的 TCP/UDP 网络负载均衡器(AWS 网络负载均衡器、GCP 外部网络负载均衡器、Azure 负载均衡器),或者您使用的是轮询模式的 DNS,那么您还可以保留客户端 IP 在 Kubernetes 内部绕过 kube-proxy 并阻止它向其他节点发送流量。**但是,您必须在每个节点上运行一个入口网关 Pod。**
|
||||
如果不这样做,那么任何接收流量但没有入口网关的节点都会丢弃流量。有关更多信息,请参阅[使用 `Type=NodePort` 的服务的源 IP](https://kubernetes.io/zh-cn/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-nodeport)。
|
||||
如果您使用的是保留客户端 IP 地址的 TCP/UDP 网络负载均衡器(AWS 网络负载均衡器、
|
||||
GCP 外部网络负载均衡器、Azure 负载均衡器),或者您使用的是轮询模式的 DNS,
|
||||
那么您还可以保留客户端 IP 在 Kubernetes 内部绕过 kube-proxy 并阻止它向其他节点发送流量。
|
||||
**但是,您必须在每个节点上运行一个入口网关 Pod。** 如果不这样做,
|
||||
那么任何接收流量但没有入口网关的节点都会丢弃流量。有关更多信息,
|
||||
请参阅[使用 `Type=NodePort` 的服务的源 IP](https://kubernetes.io/zh-cn/docs/tutorials/services/source-ip/#source-ip-for-services-with-type-nodeport)。
|
||||
使用以下命令更新入口网关以设置 `externalTrafficPolicy: Local` 以保留入口网关上的原始客户端源 IP:
|
||||
|
||||
{{< text bash >}}
|
||||
|
@ -134,7 +155,10 @@ $ kubectl patch svc istio-ingressgateway -n istio-system -p '{"spec":{"externalT
|
|||
|
||||
{{< tab name="HTTP/HTTPS Load Balancer" category-value="http" >}}
|
||||
|
||||
如果您使用的是 HTTP/HTTPS 外部负载均衡器(AWS ALB、GCP),它可以将原始客户端 IP 地址放在 X-Forwarded-For 标头中。Istio 可以通过一些配置从此标头中提取客户端 IP 地址。请参阅[配置网关网络拓扑](/zh/docs/ops/configuration/traffic-management/network-topologies/)。如果在 Kubernetes 前面使用单个负载均衡器,请参考以下快速示例:
|
||||
如果您使用的是 HTTP/HTTPS 外部负载均衡器(AWS ALB、GCP),它可以将原始客户端
|
||||
IP 地址放在 X-Forwarded-For 标头中。Istio 可以通过一些配置从此标头中提取客户端
|
||||
IP 地址。请参阅[配置网关网络拓扑](/zh/docs/ops/configuration/traffic-management/network-topologies/)。
|
||||
如果在 Kubernetes 前面使用单个负载均衡器,请参考以下快速示例:
|
||||
|
||||
{{< text yaml >}}
|
||||
apiVersion: install.istio.io/v1alpha1
|
||||
|
@ -152,7 +176,8 @@ spec:
|
|||
|
||||
{{< /tabset >}}
|
||||
|
||||
作为参考,以下是 Istio 在流行的托管 Kubernetes 环境中使用 `LoadBalancer` 服务创建的负载均衡器类型:
|
||||
作为参考,以下是 Istio 在流行的托管 Kubernetes 环境中使用 `LoadBalancer`
|
||||
服务创建的负载均衡器类型:
|
||||
|
||||
|云提供商 | 负载均衡器名称 | 负载均衡器类型
|
||||
----------------|-------------------------------|-------------------
|
||||
|
@ -162,7 +187,8 @@ spec:
|
|||
|DO DOKS | Load Balancer | Network
|
||||
|
||||
{{< tip >}}
|
||||
您可以在安装 Istio 时使用如下所示的 `serviceAnnotation` 指示 AWS EKS 创建网络负载均衡器:
|
||||
您可以在安装 Istio 时使用如下所示的 `serviceAnnotation` 指示 AWS EKS
|
||||
创建网络负载均衡器:
|
||||
|
||||
{{< text yaml >}}
|
||||
apiVersion: install.istio.io/v1alpha1
|
||||
|
@ -186,8 +212,10 @@ spec:
|
|||
|
||||
## 基于 IP 的允许列表和拒绝列表{#ip-based-allow-list-and-deny-list}
|
||||
|
||||
**何时使用 `ipBlocks` 与 `remoteIpBlocks`:** 如果您使用 X-Forwarded-For HTTP 标头或代理协议来确定原始客户端 IP 地址,那么您应该在您的 `AuthorizationPolicy` 中使用 `remoteIpBlocks`。
|
||||
如果您使用的是 `externalTrafficPolicy: Local`,那么您应该在 `AuthorizationPolicy` 中使用 `ipBlocks`。
|
||||
**何时使用 `ipBlocks` 与 `remoteIpBlocks`:** 如果您使用 X-Forwarded-For HTTP
|
||||
标头或代理协议来确定原始客户端 IP 地址,那么您应该在您的 `AuthorizationPolicy` 中使用
|
||||
`remoteIpBlocks`。如果您使用的是 `externalTrafficPolicy: Local`,那么您应该在
|
||||
`AuthorizationPolicy` 中使用 `ipBlocks`。
|
||||
|
||||
| 负载均衡器类型 | 客户端源 IP | `ipBlocks` 与 `remoteIpBlocks`
|
||||
--------------------|----------------------|---------------------------
|
||||
|
@ -195,7 +223,9 @@ spec:
|
|||
| Network | packet source address| `ipBlocks`
|
||||
| HTTP/HTTPS | X-Forwarded-For | `remoteIpBlocks`
|
||||
|
||||
* 以下命令为 Istio 入口网关创建授权策略 `ingress-policy`。以下策略将 `action` 字段设置为 `ALLOW`,以允 `ipBlocks` 中指定的 IP 地址访问入口网关。不在列表中的 IP 地址将被拒绝。`ipBlocks` 支持单个 IP 地址和 CIDR 表示法。
|
||||
* 以下命令为 Istio 入口网关创建授权策略 `ingress-policy`。以下策略将 `action`
|
||||
字段设置为 `ALLOW`,以允 `ipBlocks` 中指定的 IP 地址访问入口网关。不在列表中的
|
||||
IP 地址将被拒绝。`ipBlocks` 支持单个 IP 地址和 CIDR 表示法。
|
||||
|
||||
{{< tabset category-name="source" >}}
|
||||
|
||||
|
@ -331,7 +361,8 @@ EOF
|
|||
200
|
||||
{{< /text >}}
|
||||
|
||||
* 更新 `ingress-policy` 授权策略,将 `action` 键设置为 `DENY`,从而不允许 `ipBlocks` 中指定的 IP 地址访问入口网关:
|
||||
* 更新 `ingress-policy` 授权策略,将 `action` 键设置为 `DENY`,从而不允许
|
||||
`ipBlocks` 中指定的 IP 地址访问入口网关:
|
||||
|
||||
{{< tabset category-name="source" >}}
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ Istio 授权策略同时支持字符串类型和列表类型的 JWT 声明。
|
|||
|
||||
* 参照 [Istio 安装指南](/zh/docs/setup/install/istioctl/)安装 Istio。
|
||||
|
||||
* 部署两个工作负载(workload):`httpbin` 和 `sleep`。将它们部署在同一个命名空间中,例如 `foo`。每个工作负载都在前面运行一个 Envoy 代理。 你可以使用以下命令来部署它们:
|
||||
* 部署两个工作负载(workload):`httpbin` 和 `sleep`。将它们部署在同一个命名空间中,
|
||||
* 例如 `foo`。每个工作负载都在前面运行一个 Envoy 代理。 你可以使用以下命令来部署它们:
|
||||
|
||||
{{< text bash >}}
|
||||
$ kubectl create ns foo
|
||||
|
@ -44,7 +45,9 @@ Istio 授权策略同时支持字符串类型和列表类型的 JWT 声明。
|
|||
|
||||
## 允许包含有效 JWT 和 列表类型声明的请求
|
||||
|
||||
1. 以下命令为 `foo` 命名空间下的 `httpbin` 工作负载创建一个名为 `jwt-example` 的身份验证策略。这个策略使得 `httpbin` 工作负载接收 Issuer 为 `testing@secure.istio.io` 的 JWT 令牌:
|
||||
1. 以下命令为 `foo` 命名空间下的 `httpbin` 工作负载创建一个名为 `jwt-example`
|
||||
的身份验证策略。这个策略使得 `httpbin` 工作负载接收 Issuer 为 `testing@secure.istio.io`
|
||||
的 JWT 令牌:
|
||||
|
||||
{{< text bash >}}
|
||||
$ kubectl apply -f - <<EOF
|
||||
|
@ -77,7 +80,10 @@ Istio 授权策略同时支持字符串类型和列表类型的 JWT 声明。
|
|||
200
|
||||
{{< /text >}}
|
||||
|
||||
1. 以下命令为 `foo` 命名空间下的 `httpbin` 工作负载创建一个名为 `require-jwt` 的授权策略。 这个策略要求所有发往 `httpbin` 服务的请求都要包含一个将 `requestPrincipal` 设置为 `testing@secure.istio.io/testing@secure.istio.io` 的有效 JWT。Istio 使用 `/` 连接 JWT 令牌的 `iss` 和 `sub` 以组成 `requestPrincipal` 字段。
|
||||
1. 以下命令为 `foo` 命名空间下的 `httpbin` 工作负载创建一个名为 `require-jwt`
|
||||
的授权策略。这个策略要求所有发往 `httpbin` 服务的请求都要包含一个将 `requestPrincipal`
|
||||
设置为 `testing@secure.istio.io/testing@secure.istio.io` 的有效 JWT。Istio 使用
|
||||
`/` 连接 JWT 令牌的 `iss` 和 `sub` 以组成 `requestPrincipal` 字段。
|
||||
|
||||
{{< text syntax="bash" expandlinks="false" >}}
|
||||
$ kubectl apply -f - <<EOF
|
||||
|
@ -98,7 +104,8 @@ Istio 授权策略同时支持字符串类型和列表类型的 JWT 声明。
|
|||
EOF
|
||||
{{< /text >}}
|
||||
|
||||
1. 获取 `iss` 和 `sub` 都为 `testing@secure.istio.io` 的 JWT。这会让 Istio 生成的 `requestPrincipal` 属性值为 `testing@secure.istio.io/testing@secure.istio.io`:
|
||||
1. 获取 `iss` 和 `sub` 都为 `testing@secure.istio.io` 的 JWT。这会让 Istio 生成的
|
||||
`requestPrincipal` 属性值为 `testing@secure.istio.io/testing@secure.istio.io`:
|
||||
|
||||
{{< text syntax="bash" expandlinks="false" >}}
|
||||
$ TOKEN=$(curl {{< github_file >}}/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -
|
||||
|
|
|
@ -10,9 +10,11 @@ test: yes
|
|||
该任务阐述了如何在不更改授权策略的前提下从一个信任域迁移到另一个。
|
||||
|
||||
在 Istio 1.4 中,我们引入了一个 alpha 特性以支持授权策略 {{< gloss >}}trust domain migration{{</ gloss >}}。
|
||||
这意味着如果一个 Istio 网格需要改变它的 {{< gloss >}}trust domain{{</ gloss >}},其授权策略是不需要手动更新的。
|
||||
在 Istio 中,如果一个 {{< gloss >}}workload{{</ gloss >}} 运行在命名空间 `foo` 中,服务账户为 `bar`,系统的信任域为 `my-td`,那么该工作负载的身份就是 `spiffe://my-td/ns/foo/sa/bar`。
|
||||
默认情况下,Istio 网格的信任域是 `cluster.local`,除非您在安装时另外指定了。
|
||||
这意味着如果一个 Istio 网格需要改变它的 {{< gloss >}}trust domain{{</ gloss >}},
|
||||
其授权策略是不需要手动更新的。在 Istio 中,如果一个 {{< gloss >}}workload{{</ gloss >}}
|
||||
运行在命名空间 `foo` 中,服务账户为 `bar`,系统的信任域为 `my-td`,那么该工作负载的身份就是
|
||||
`spiffe://my-td/ns/foo/sa/bar`。默认情况下,Istio 网格的信任域是 `cluster.local`,
|
||||
除非您在安装时另外指定了。
|
||||
|
||||
## 开始之前{#before-you-begin}
|
||||
|
||||
|
@ -26,7 +28,9 @@ test: yes
|
|||
$ istioctl install --set profile=demo --set meshConfig.trustDomain=old-td
|
||||
{{< /text >}}
|
||||
|
||||
1. 将 [httpbin]({{< github_tree >}}/samples/httpbin) 示例部署于 `default` 命名空间中,将 [sleep]({{< github_tree >}}/samples/sleep) 示例部署于 `default` 和 `sleep-allow` 命名空间中:
|
||||
1. 将 [httpbin]({{< github_tree >}}/samples/httpbin) 示例部署于 `default` 命名空间中,
|
||||
将 [sleep]({{< github_tree >}}/samples/sleep) 示例部署于 `default` 和 `sleep-allow`
|
||||
命名空间中:
|
||||
|
||||
{{< text bash >}}
|
||||
$ kubectl label namespace default istio-injection=enabled
|
||||
|
@ -119,10 +123,11 @@ test: yes
|
|||
403
|
||||
{{< /text >}}
|
||||
|
||||
这是因为我们指定了一个授权策略,它会拒绝所有到 `httpbin` 的请求,除非请求来源的身份是 `old-td/ns/sleep-allow/sa/sleep`,而这个身份是 `sleep-allow` 命名空间的 `sleep` 的旧身份。
|
||||
当我们迁移到一个新的信任域,即 `new-td`,`sleep` 应用的身份就变成 `new-td/ns/sleep-allow/sa/sleep`,与 `old-td/ns/sleep-allow/sa/sleep` 不同。
|
||||
因此,`sleep-allow` 命名空间中的 `sleep` 应用之前的请求被放行,但现在被拒绝。
|
||||
在 Istio 1.4 之前,修复该问题的唯一方式就是手动调整授权策略。
|
||||
这是因为我们指定了一个授权策略,它会拒绝所有到 `httpbin` 的请求,除非请求来源的身份是
|
||||
`old-td/ns/sleep-allow/sa/sleep`,而这个身份是 `sleep-allow` 命名空间的 `sleep` 的旧身份。
|
||||
当我们迁移到一个新的信任域,即 `new-td`,`sleep` 应用的身份就变成 `new-td/ns/sleep-allow/sa/sleep`,
|
||||
与 `old-td/ns/sleep-allow/sa/sleep` 不同。因此,`sleep-allow` 命名空间中的 `sleep`
|
||||
应用之前的请求被放行,但现在被拒绝。在 Istio 1.4 之前,修复该问题的唯一方式就是手动调整授权策略。
|
||||
而在 Istio 1.4 中,我们引入了一种更简单的方法,如下所示。
|
||||
|
||||
## 使用别名迁移信任域{#migrate-trust-domain-with-trust-domain-aliases}
|
||||
|
@ -164,7 +169,8 @@ test: yes
|
|||
例如,应该是 `cluster.local/ns/sleep-allow/sa/sleep`,而不是 `old-td/ns/sleep-allow/sa/sleep`。
|
||||
请注意,在这种情况下,`cluster.local` 并不是 Istio 网格的信任域(信任域依然是 `old-td`)。
|
||||
在策略中,`cluster.local` 是一个指针,指向当前信任域,即 `old-td`(后来是 `new-td`)及其别名。
|
||||
通过在授权策略中使用 `cluster.local`,当您迁移到新的信任域时,Istio 将检测到此情况,并将新的信任域视为旧的信任域,而无需包含别名。
|
||||
通过在授权策略中使用 `cluster.local`,当您迁移到新的信任域时,Istio 将检测到此情况,
|
||||
并将新的信任域视为旧的信任域,而无需包含别名。
|
||||
|
||||
## 清理{#clean-up}
|
||||
|
||||
|
|
Loading…
Reference in New Issue