JWTクレームに基づくルーティング
このタスクでは、リクエスト認証と仮想サービスを使用して、Istioイングレスゲートウェイ上のJWTクレームに基づいてリクエストをルーティングする方法を示します。
注:この機能は Istio Ingress Gateway のみをサポートしており、JWTクレームに基づいて適切に検証およびルーティングを行うためには、リクエスト認証と仮想サービスの両方を使用する必要があります。
始める前に
Istioインストールガイドを使用してIstioをインストールしてください。
ワークロード
httpbin
を名前空間(例:foo
)にデプロイし、このコマンドでIstio Ingress Gatewayを通して公開します。$ 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
Ingress IPとポートの決定の指示に従って、
INGRESS_HOST
とINGRESS_PORT
の環境変数を定義します。このコマンドを使用して、
httpbin
ワークロードとIngress Gatewayが期待どおりに動作していることを確認します。$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n" 200
JWTクレームに基づくイングレスルーティングの設定
Istio Ingress Gatewayは、認証済みのJWTに基づいてルーティングをサポートしており、エンドユーザーのIDに基づいてルーティングするのに役立ち、認証されていない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 Ingress GatewayでのJWT検証が有効になり、検証済みのJWTクレームを後でルーティングの目的で仮想サービスで使用できるようになります。
JWTクレームベースのルーティングはIngress Gatewayでのみサポートされているため、リクエスト認証はIngress Gatewayに適用されます。
注:リクエスト認証は、リクエストに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
と一致させます。プレフィックス@
は、HTTPヘッダーではなく、JWT検証から派生したメタデータと一致していることを示します。文字列型、文字列リスト型、およびネストされたクレームがサポートされています。ネストされたクレーム名には、セパレーターとして
.
または[]
を使用します。たとえば、"@request.auth.claims.name.givenName"
または"@request.auth.claims[name][givenName]"
は、ネストされたクレームname
とgivenName
に一致します。これらはここで同等です。クレーム名に.
が含まれている場合は、セパレーターとして[]
のみを使用できます。
JWTクレームに基づくイングレスルーティングの検証
JWTがない場合にIngress GatewayがHTTPコード404を返すことを検証します。
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" HTTP/1.1 404 Not Found ...
JWTがない場合にHTTPコード403でリクエストを明示的に拒否する認可ポリシーを作成することもできます。
無効なJWTの場合にIngress Gatewayが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トークンでリクエストがIngress Gatewayによってルーティングされることを検証します。$ 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
が含まれていない場合、Ingress Gatewayが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