基於 JWT 宣告的路由
此任務向您展示如何使用請求驗證和虛擬服務,根據 Istio 入口閘道上的 JWT 宣告來路由請求。
注意:此功能僅支援 Istio 入口閘道,並且需要同時使用請求驗證和虛擬服務,才能正確驗證並根據 JWT 宣告進行路由。
開始之前
使用 Istio 安裝指南 安裝 Istio。
在命名空間中部署一個工作負載,例如
foo
中的httpbin
,並使用以下命令通過 Istio 入口閘道公開它$ kubectl create ns foo $ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo $ kubectl apply -f @samples/httpbin/httpbin-gateway.yaml@ -n foo
按照確定入口 IP 和端口中的說明,定義
INGRESS_HOST
和INGRESS_PORT
環境變數。使用以下命令驗證
httpbin
工作負載和入口閘道是否按預期運作$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
根據 JWT 宣告設定入口路由
Istio 入口閘道支援基於已驗證的 JWT 的路由,這對於基於最終用戶身份進行路由非常有用,並且比使用未經身份驗證的 HTTP 屬性(例如路徑或標頭)更安全。
為了基於 JWT 聲明進行路由,首先創建請求身份驗證以啟用 JWT 驗證
$ kubectl apply -f - <<EOF apiVersion: security.istio.io/v1 kind: RequestAuthentication metadata: name: ingress-jwt namespace: istio-system spec: selector: matchLabels: istio: ingressgateway jwtRules: - issuer: "testing@secure.istio.io" jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/jwks.json" EOF
請求身份驗證在 Istio 入口閘道上啟用 JWT 驗證,以便稍後可以在虛擬服務中使用經過驗證的 JWT 聲明進行路由。
請求身份驗證應用於入口閘道,因為基於 JWT 聲明的路由僅在入口閘道上支援。
注意:請求身份驗證僅在請求中存在 JWT 時才會檢查 JWT。若要使 JWT 成為必需並在請求不包含 JWT 時拒絕請求,請應用任務中指定的授權策略。
更新虛擬服務以基於已驗證的 JWT 聲明進行路由
$ kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: httpbin namespace: foo spec: hosts: - "*" gateways: - httpbin-gateway http: - match: - uri: prefix: /headers headers: "@request.auth.claims.groups": exact: group1 route: - destination: port: number: 8000 host: httpbin EOF
虛擬服務使用保留標頭
"@request.auth.claims.groups"
來匹配 JWT 聲明groups
。前綴@
表示它與從 JWT 驗證衍生的元數據匹配,而不是與 HTTP 標頭匹配。支援字串類型、字串列表和巢狀聲明的聲明。使用
.
或[]
作為巢狀聲明名稱的分隔符。例如,"@request.auth.claims.name.givenName"
或"@request.auth.claims[name][givenName]"
匹配巢狀聲明name
和givenName
,它們在這裡是等效的。當聲明名稱包含.
時,只能使用[]
作為分隔符。
驗證基於 JWT 宣告的入口路由
驗證入口閘道在沒有 JWT 的情況下返回 HTTP 代碼 404
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" HTTP/1.1 404 Not Found ...
您還可以創建授權策略,以便在缺少 JWT 時明確拒絕請求並返回 HTTP 代碼 403。
驗證入口閘道在 JWT 無效的情況下返回 HTTP 代碼 401
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer some.invalid.token" HTTP/1.1 401 Unauthorized ...
401 由請求身份驗證返回,因為 JWT 未通過驗證。
驗證入口閘道是否使用包含聲明
groups: group1
的有效 JWT 令牌路由請求$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode {"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"}
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer $TOKEN_GROUP" HTTP/1.1 200 OK ...
驗證入口閘道在有效 JWT 但不包含聲明
groups: group1
的情況下返回 HTTP 代碼 404$ TOKEN_NO_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.24/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN_NO_GROUP" | cut -d '.' -f2 - | base64 --decode {"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer $TOKEN_NO_GROUP" HTTP/1.1 404 Not Found ...
清除
刪除命名空間
foo
$ kubectl delete namespace foo
刪除請求身份驗證
$ kubectl delete requestauthentication ingress-jwt -n istio-system