基于组和列表类型声明的授权
本教程将向您介绍在 Istio 中配置基于组的授权和列表类型声明的授权的示例。
开始之前
阅读授权概念并阅读有关如何配置 Istio 授权的指南。
阅读 Istio 身份验证策略和相关的双向 TLS 身份验证概念。
创建一个安装了 Istio 并启用了双向 TLS 的 Kubernetes 集群。要满足此先决条件,您可以按照 Kubernetes 安装说明进行操作。
设置所需的命名空间和服务
本教程在一个名为 rbac-groups-test-ns
的新命名空间中运行,该命名空间有两个服务,httpbin
和 sleep
,两者都运行在 Envoy sidecar 代理上。以下命令设置环境变量以存储命名空间的名称,创建命名空间,并启动这两个服务。
在运行以下命令之前,需要输入包含 Istio 安装文件的目录。
将
NS
环境变量的值设置为rbac-listclaim-test-ns
:$ export NS=rbac-groups-test-ns
确保
NS
环境变量指向仅测试命名空间。运行以下命令以删除NS
环境变量指向的命名空间中的所有资源。$ kubectl delete namespace $NS
为本教程创建名称空间:
$ kubectl create ns $NS
创建
httpbin
和sleep
服务和部署:$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n $NS $ kubectl apply -f <(istioctl kube-inject -f @samples/sleep/sleep.yaml@) -n $NS
要验证
httpbin
和sleep
服务是否正在运行并且sleep
能够到达httpbin
,请运行以下 curl 命令:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n"
当命令成功时,它返回 HTTP 代码 200。
使用双向TLS配置JSON Web令牌(JWT)身份验证
您接下来应用的身份验证策略强制要求访问 httpbin
服务需要有效的 JWT。
策略中定义的 JSON Web 密钥集( JWKS )端点必须对 JWT 进行签名。
本教程使用 Istio 代码库中的JWKS 端点并使用此示例 JWT。
示例 JWT 包含一个带有 groups
声明键和一个字符串列表的 JWT 声明,["group1"
,"group2"
]作为声明值。
JWT 声明值可以是字符串或字符串列表;两种类型都受支持。
应用身份验证策略以要求
httpbin
的双向 TLS 和 JWT 身份验证。$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "authentication.istio.io/v1alpha1" kind: "Policy" metadata: name: "require-mtls-jwt" spec: targets: - name: httpbin peers: - mtls: {} origins: - jwt: issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.2/security/tools/jwt/samples/jwks.json" principalBinding: USE_ORIGIN EOF
设置
TOKEN
环境变量以包含有效的示例 JWT。$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.2/security/tools/jwt/samples/groups-scope.jwt -s)
连接到
httpbin
服务:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
附加有效的 JWT 时,它返回 HTTP 代码 200。
在未连接 JWT 时验证与
httpbin
服务的连接是否失败:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n"
当没有附加有效的 JWT 时,它返回 HTTP 代码 401。
配置基于组的授权
如果请求来自特定组,则本节创建一个策略以授权访问 httpbin
服务。
由于缓存和其他传播开销可能会有一些延迟,因此请等待新定义的 RBAC 策略生效。
为命名空间启用 Istio RBAC:
$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "rbac.istio.io/v1alpha1" kind: ClusterRbacConfig metadata: name: default spec: mode: 'ON_WITH_INCLUSION' inclusion: namespaces: ["rbac-groups-test-ns"] EOF
一旦 RBAC 策略生效,验证 Istio 是否拒绝了与
httpbin
服务的 curl 连接:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
一旦 RBAC 策略生效,该命令返回 HTTP 代码 403。
要提供对
httpbin
服务的读访问权,请创建httpbin-viewer
服务角色:$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRole metadata: name: httpbin-viewer namespace: rbac-groups-test-ns spec: rules: - services: ["httpbin.rbac-groups-test-ns.svc.cluster.local"] methods: ["GET"] EOF
要将
httpbin-viewer
角色分配给group1
中的用户,请创建bind-httpbin-viewer
服务角色绑定。$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: bind-httpbin-viewer namespace: rbac-groups-test-ns spec: subjects: - properties: request.auth.claims[groups]: "group1" roleRef: kind: ServiceRole name: "httpbin-viewer" EOF
或者,您可以在
subject
下指定group
属性。指定组的两种方式都是等效的。目前,Istio 仅支持在 JWT 中为request.auth.claims
属性和subject
下的group
属性进行匹配。要在
subject
下指定group
属性,请使用以下命令:$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: bind-httpbin-viewer namespace: rbac-groups-test-ns spec: subjects: - group: "group1" roleRef: kind: ServiceRole name: "httpbin-viewer" EOF
等待新定义的 RBAC 策略生效。
RBAC 策略生效后,验证与
httpbin
服务的连接是否成功:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
HTTP Header 包括一个有效的 JWT,其
groups
声明值为["group1"
,"group2"
],因为它包含group1
,所以返回 HTTP 代码 200。
配置列表类型声明的授权
Istio RBAC 支持配置列表类型声明的授权。
示例 JWT 包含一个带有 scope
声明键和一个字符串列表的 JWT 声明,["scope1"
,"scope2"
]作为声明值。
您可以使用 gen-jwt
python 脚本生成带有其他列表类型声明的 JWT 以进行测试。
按照 gen-jwt
脚本中的说明使用 gen-jwt.py
文件。
要将
httpbin-viewer
角色分配给具有 JWT 的请求,该请求包含值为scope1
的列表类型scope
声明,请创建名为bind-httpbin-viewer
的服务角色绑定:$ cat <<EOF | kubectl apply -n $NS -f - apiVersion: "rbac.istio.io/v1alpha1" kind: ServiceRoleBinding metadata: name: bind-httpbin-viewer namespace: rbac-groups-test-ns spec: subjects: - properties: request.auth.claims[scope]: "scope1" roleRef: kind: ServiceRole name: "httpbin-viewer" EOF
等待新定义的 RBAC 策略生效。
RBAC 策略生效后,验证与
httpbin
服务的连接是否成功:$ kubectl exec $(kubectl get pod -l app=sleep -n $NS -o jsonpath={.items..metadata.name}) -c sleep -n $NS -- curl http://httpbin.$NS:8000/ip -s -o /dev/null -w "%{http_code}\n" --header "Authorization: Bearer $TOKEN"
HTTP Header 包括一个有效的 JWT,
scope
的声明值为["scope1"
,"scope2"
],因为它包含scope1
, 所以返回 HTTP 代码 200。
清理
完成本教程后,运行以下命令以删除在命名空间中创建的所有资源。
$ kubectl delete namespace $NS