このトピックでは、Alibaba Cloud Service Mesh (ASM) における JSON Web Token (JWT) 認証に関するよくある質問、JWT アルゴリズムのサポート、クラスター内外のサービスに対する JwksUri の設定、およびパスレベルの認証除外について説明します。
前提条件
ASM インスタンスが作成されていること。
JwksUri 関連の設定には、ASM 1.13 以降が必要です。
データプレーンクラスターの kubeconfig が設定され、
kubectlコマンドを実行できること。
ASM がサポートする JWT アルゴリズム
1.13 より前のバージョンの ASM は、RSA アルゴリズムのみをサポートします。
ASM 1.13 以降では、次の JWT アルゴリズムがサポートされています:ES256、ES384、ES512、HS256、HS384、HS512、RS256、RS384、RS512、PS256、PS384、PS512、および EdDSA。
ASM における JwksUri の使用方法
Alibaba Cloud Service Mesh 1.13 以降を使用する必要があります。JwksUri を使用するには、2 つの方法があります。
JwksUri がクラスター内のサービスを指している場合は、直接設定できます。
JwksUri がクラスター外のサービスを指している場合は、対応する ServiceEntry を設定する必要があります。
このトピックでは、Istio の公式 JWT および Jwks サンプルを例に説明します。詳細については、「JWT」および「Jwks」をご参照ください。
クラスター内の JwksUri アドレスの使用
このトピックでは、JwksUri アドレスが Service Mesh が管理するクラスター内のアドレスであることを前提としています。nginx-proxy はクラスター内のサービスです。ポート 80 の /get_jwks エンドポイントは jwks 公開キー情報を返し、JwksUri は http://nginx-proxy.{Namespace}.svc.cluster.local:80/get_jwks です。
次のコマンドを実行して、クラスターの get_jwks エンドポイントが利用可能かどうかを確認します。
curl nginx-proxy/get_jwks期待される出力:
{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65p****-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYt****-91gVuoeJT_DwtGGcp4ignkgXfkiE****-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]}キーデータを含む
200レスポンスは、get_jwks エンドポイントが利用可能であることを示します。リクエスト認証を作成します。
ASM コンソール にログオンします。
左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、設定する ASM インスタンスを見つけます。 ASM インスタンスの名前をクリックするか、[管理][アクション] 列の をクリックします。
左側メニューで、セキュリティ管理 > リクエスト身分認証 (Request Authentication) をクリックします。
リクエスト身分認証 (Request Authentication) ページで YAML で作成 をクリックし、ターゲットの 名前空間 と任意の シナリオテンプレート を選択し、次の YAML を設定してから 作成 をクリックします。
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: testing@secure.istio.io jwksUri: 'http://nginx-proxy/get_jwks' selector: matchLabels: app: httpbin
データプレーンの kubeconfig を使用し、次のコマンドを実行して httpbin サービスにアクセスします。
# TOKEN 環境変数を設定します。
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.14/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode -
# sleep Pod から JWT を使用して httpbin サービスにアクセスします。
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"ステータスコード 200 は、リクエストが成功したことを示します。
クラスター外の JwksUri アドレスの使用
次の例は HTTP プロトコルに基づいています。HTTPS を使用して Jwks を取得する必要がある場合は、ServiceEntry に追加の宛先ルールを設定する必要があります。
リモートアドレス用に ServiceEntry を作成します。
a. 次の YAML 内容を使用して、service-entry.yaml を作成します。
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-svc-https namespace: foo spec: addresses: - 11.11.XX.XX # 外部 Jwks サービスのアドレスに置き換えます。 endpoints: - address: 11.11.XX.XX # 外部 Jwks サービスのアドレスに置き換えます。 hosts: - 11.11.XX.XX # 外部 Jwks サービスのアドレスに置き換えます。 location: MESH_EXTERNAL ports: - name: http number: 80 protocol: HTTP - name: https number: 443 protocol: HTTPS resolution: STATICb. 次のコマンドを実行して、ServiceEntry をデプロイします。
kubectl apply -f service-entry.yaml(オプション) jwks サービスが HTTPS プロトコルを必要とする場合は、ServiceEntry に追加の宛先ルールを設定する必要があります。
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: external-svc-https namespace: foo spec: host:trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE リクエスト認証を作成します。
ASM コンソール にログオンします。
左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、設定する ASM インスタンスを見つけます。 ASM インスタンスの名前をクリックするか、[管理][アクション] 列の をクリックします。
左側メニューで、セキュリティ管理 > リクエスト身分認証 (Request Authentication) をクリックします。
リクエスト身分認証 (Request Authentication) ページで YAML で作成 をクリックし、ターゲットの 名前空間 と任意の シナリオテンプレート を選択し、次の YAML を設定してから 作成 をクリックします。
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: testing@secure.istio.io jwksUri: '${YOUR_EXTERNAL_JWKS_URI}' selector: matchLabels: app: httpbin
次のコマンドを実行して TOKEN 環境変数を設定し、sleep Pod からアクセステストを実行します。
# TOKEN 環境変数を設定します。
TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.14/security/tools/jwt/samples/demo.jwt -s)
# sleep Pod から JWT を使用して httpbin サービスにアクセスします。
kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" -c sleep -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"ステータスコード 200 は、リクエストが成功したことを示します。
特定パスへのリクエストに対する JWT 認証のスキップ
ASM コンソールには認可ポリシー機能があります。認可ポリシーで除外一致を設定して、指定したパス以外のパスへのリクエストを認証できます。
サービスをデプロイしてアクセスします。
a. ASM インスタンスに関連付けられたクラスターに Bookinfo サンプルアプリケーションをデプロイします。詳細については、「ASM インスタンスに関連付けられたクラスターにアプリケーションをデプロイする」をご参照ください。
b. 次のコマンドを実行して、以下の 3 つのサービスにアクセスし、各パスが利用可能であることを確認します。
curl "http://${ASM_GATEWAY_ADDRESS}/productpage" -sS -o /dev/null -w "%{http_code}\n" curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n" curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n"3 つのサービスすべてが
200を返し、サービスがアクセス可能であることを示します。RequestAuthentication を作成します。
ASM コンソール にログオンします。
左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、設定する ASM インスタンスを見つけます。 ASM インスタンスの名前をクリックするか、[管理][アクション] 列の をクリックします。
左側メニューで、セキュリティ管理 > リクエスト身分認証 (Request Authentication) をクリックします。
リクエスト身分認証 (Request Authentication) ページで YAML で作成 をクリックし、ターゲットの 名前空間 と任意の シナリオテンプレート を選択し、次の YAML を設定してから 作成 をクリックします。
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: istio-system spec: jwtRules: - issuer: testing@secure.istio.io jwks: >- { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVu****_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]} selector: matchLabels: app: istio-ingressgatewayこのリクエスト認証は ASM ゲートウェイに適用され、ゲートウェイを通過するすべてのリクエストで有効になります。RequestAuthentication を設定すると、JWT のないリクエストと正しい JWT を持つリクエストの両方が許可されます。不正な JWT を持つリクエストのみが拒否されます。
AuthorizationPolicy を作成します。
特定のパスへのリクエストでは JWT を不要とし、それ以外のパスでは JWT を必須とするように設定します。このトピックでは、/productpage パスを例に説明します。/productpage パスでは JWT 認証は実行されません。/productpage パス以外の 2 つのパスについては、リクエストが通過するには正しい JWT が必要です。
ASM コンソール にログオンします。
左側のナビゲーションウィンドウで、 を選択します。
[メッシュ管理] ページで、設定する ASM インスタンスを見つけます。 ASM インスタンスの名前をクリックするか、[管理][アクション] 列の をクリックします。
左側メニューで、セキュリティ管理 > 権限付与ポリシー (Authorization Policy) をクリックします。
権限付与ポリシー (Authorization Policy) ページで YAML で作成 をクリックし、ターゲットの 名前空間 と任意の シナリオテンプレート を選択し、次の YAML を設定してから 作成 をクリックします。
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: test-exclude namespace: istio-system spec: action: DENY rules: - from: - source: notRequestPrincipals: - '*' to: - operation: notPaths: - /productpage selector: matchLabels: app: istio-ingressgatewayこの AuthorizationPolicy も ASM ゲートウェイに適用されます。このポリシーは主に、/productpage パス以外のパスへのリクエストで正しい JWT がない場合にアクセスを拒否するという、1つの DENY ルールを設定します。
アクセステストを実行します。
a. 次のコマンドを実行して、リクエストに含める JWT を TOKEN 環境変数として設定します。
export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1****.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5p****.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9****-LS9qd_vpdLG4Tn1A15NxfCjp5f7Q****-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZz****__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCg****_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3UcMI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvH****_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8****b. 次のコマンドを実行して、3 つのサービスパスにアクセスします。
どのリクエストにも JWT がない場合:
curl "http://${ASM_GATEWAY_ADDRESS}/productpage" -sS -o /dev/null -w "%{http_code}\n"
curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n"
curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n"期待される出力:
200
403
403/productpage パスのみがアクセス可能です。他のすべてのパスは 403 を返します。
すべてのリクエストに JWT がある場合:
curl "http://${ASM_GATEWAY_ADDRESS}/productpage" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n"
curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/0" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n"
curl "http://${ASM_GATEWAY_ADDRESS}/api/v1/products/1" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n"期待される出力:
200
200
2003 つのパスすべてが 200 を返し、すべてがアクセス可能であることを示します。