全部產品
Search
文件中心

Alibaba Cloud Service Mesh:JWT FAQ

更新時間:Nov 21, 2024

本文介紹JWT相關的常見問題。

ASM支援哪些JWT演算法?

  • ASM版本<1.13,只支援RSA演算法。

  • ASM版本≥1.13,支援JWT演算法,包括ES256、ES384、ES512、HS256、HS384、HS512、RS256、RS384、RS512、PS256、PS384、PS512和EdDSA。

如何在ASM中使用JwksUri?

您需要使用阿里雲Service MeshASM的1.13及以上版本進行設定。使用JwksUri主要分為以下兩種情況:

  • JwksUri的地址為叢集內部的服務:可以直接進行配置。

  • JwksUri為叢集外部的服務:需要配置對應的ServiceEntry。

本文以Istio官方的JWT和Jwks為例進行說明,詳情請參見JWTJwks

使用叢集內的JwksUri地址

本文假設JwksUri地址是Service MeshASM管理的叢集中的地址,nginx-proxy是叢集內的一個服務,在80連接埠的/get_jwks介面會返回jwks公開金鑰資訊,JwksUrihttp://nginx-proxy.{Namespace}.svc.cluster.local:80/get_jwks

  1. 執行以下命令,查看叢集的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****"}]}

    輸出如上結果,表示get_jwks介面可用。

  2. 建立請求認證。

    1. 登入ASM控制台

    2. 在左側導覽列,選擇服務網格 > 網格管理

    3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

    4. 在左側導覽列單擊網格資訊安全中心 > 請求身份認證

    5. 請求身份認證頁面,單擊使用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
  3. 使用資料面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配置額外的目標規則。

  1. 為遠端地址建立ServiceEntry。

    1. 使用以下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: STATIC                           
    2. 執行以下命令,部署ServiceEntry。

      kubectl apply -f service-entry.yaml
  2. (可選)如果您的jwks服務需要使用HTTPS協議,需要額外為該ServiceEntry配置一個DestinationRule。

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: external-svc-https
      namespace: foo
    spec:
      host: ${ServiceEntry對應的host}
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN
        portLevelSettings:
          - port:
              number: 443
            tls:
              mode: SIMPLE
  3. 建立請求認證。

    1. 登入ASM控制台

    2. 在左側導覽列,選擇服務網格 > 網格管理

    3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

    4. 在左側導覽列單擊網格資訊安全中心 > 請求身份認證

    5. 請求身份認證頁面單擊使用YAML建立,選擇目標命名空間和任意情境模板,配置如下YAML,然後單擊建立

      apiVersion: security.istio.io/v1beta1
      kind: RequestAuthentication
      metadata:
        name: jwt-example
        namespace: foo
      spec:
        jwtRules:
          - issuer: tes****@secure.istio.io
            jwksUri: '${外部jwksUri}'
        selector:
          matchLabels:
            app: httpbin
  4. 執行以下命令,在sleep Pod中進行訪問測試。

    # 從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控制台提供了授權策略功能,您可以在授權策略中配置“排除匹配”,選擇對某些路徑之外的請求進行鑒權。

  1. 部署並訪問服務。

    1. 在ASM關聯的叢集中部署Bookinfo應用樣本。具體操作,請參見在ASM執行個體關聯的叢集中部署應用

    2. 執行以下命令,訪問如下三個服務,確保各個路徑可用。

      curl "http://${ASM網關地址}/productpage" -sS -o /dev/null  -w "%{http_code}\n"
      curl "http://${ASM網關地址}/api/v1/products/0" -sS -o /dev/null  -w "%{http_code}\n"
      curl "http://${ASM網關地址}/api/v1/products/1" -sS -o /dev/null  -w "%{http_code}\n"

      三個服務均返回200,說明訪問成功。

  2. 建立RequestAuthentication。

    1. 登入ASM控制台

    2. 在左側導覽列,選擇服務網格 > 網格管理

    3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

    4. 在左側導覽列單擊網格資訊安全中心 > 請求身份認證

    5. 請求身份認證頁面單擊使用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的請求會被拒絕。

  3. 建立AuthorizationPolicy。

    設定特定路徑的請求不需要攜帶JWT,其餘路徑的請求必須攜帶JWT。本文以/productpage路徑為例,對於/productpage路徑不進行JWT鑒權;對於除了/productpage路徑以外的兩個路徑,請求必須攜帶正確的JWT才可以通過。

    1. 登入ASM控制台

    2. 在左側導覽列,選擇服務網格 > 網格管理

    3. 網格管理頁面,找到待配置的執行個體,單擊執行個體的名稱或在操作列中單擊管理

    4. 在左側導覽列單擊網格資訊安全中心 > 授權策略

    5. 授權策略頁面單擊使用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網關,主要配置了一條DENY規則:對於除了/productpage路徑以外的請求,如果沒有攜帶正確的JWT,就會拒絕訪問。

  4. 進行訪問測試。

    1. 執行以下命令,將請求攜帶的JWT設定為環境變數TOKEN。

      export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1****.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5p****.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9****-LS9qd_vpdLG4Tn1A15NxfCjp5f7Q****-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZz****__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCg****_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvH****_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8****
    2. 執行以下命令,訪問三個服務路徑。

      • 所有請求都不攜帶JWT:

        curl "http://${ASM網關地址}/productpage" -sS -o /dev/null  -w "%{http_code}\n"
        200
        
        curl "http://${ASM網關地址}/api/v1/products/0" -sS -o /dev/null  -w "%{http_code}\n"
        403
        
        curl "http://${ASM網關地址}/api/v1/products/1" -sS -o /dev/null  -w "%{http_code}\n"
        403

        可以看到,只有/productpage路徑可以被訪問,其餘路徑都返回403

      • 所有請求都攜帶JWT:

        curl "http://${ASM網關地址}/productpage" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null  -w "%{http_code}\n"
        200
        
        curl "http://${ASM網關地址}/api/v1/products/0" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null  -w "%{http_code}\n"
        200
        
        curl "http://${ASM網關地址}/api/v1/products/1" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null  -w "%{http_code}\n"
        200

        可以看到,三個路徑均返回200,表示都可以被訪問。