全部產品
Search
文件中心

Alibaba Cloud Service Mesh:對HTTP請求中的JWT進行認證和鑒權

更新時間:Jun 30, 2024

當您需要在服務網格中驗證和授權HTTP請求來源時,可以配置JWT(JSON Web Token)請求鑒權,實現來源認證(終端使用者認證)。在處理請求時,該配置能夠準確核實要求標頭中Access Token的有效性,只允許來源可信的請求訪問服務,提高服務的安全性,並簡化服務間身分識別驗證的複雜性。

前提條件

已添加叢集到ASM執行個體,且ASM執行個體版本為1.6及以上。

背景資訊

Service Mesh包含兩種認證方式:

  • 傳輸認證:基於雙向TLS技術,常用於服務間通訊認證。

  • 來源認證:基於JWT技術,常用於用戶端和服務之間的請求認證。

JWT是一種用於雙方之間傳遞安全資訊的表述性聲明規範。關於JWT的更多資訊,請參見JWT官方文檔

步驟一:建立命名空間並部署樣本服務

  1. 建立foo命名空間,設定標籤名稱為istio-injection,值為enabled。具體操作,請參見管理全域命名空間

  2. 使用以下內容,建立httpbin.yaml和sleep.yaml。

    展開查看httpbin.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
     name: httpbin
    ---
    apiVersion: v1
    kind: Service
    metadata:
     name: httpbin
     labels:
     app: httpbin
     service: httpbin
    spec:
     ports:
     - name: http
     port: 8000
     targetPort: 80
     selector:
     app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: httpbin
    spec:
     replicas: 1
     selector:
     matchLabels:
     app: httpbin
     version: v1
     template:
     metadata:
     labels:
     app: httpbin
     version: v1
     spec:
     serviceAccountName: httpbin
     containers:
     - image: docker.io/kennethreitz/httpbin
     imagePullPolicy: IfNotPresent
     name: httpbin
     ports:
     - containerPort: 80

    展開查看sleep.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: sleep
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sleep
      labels:
        app: sleep
        service: sleep
    spec:
      ports:
      - port: 80
        name: http
      selector:
        app: sleep
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sleep
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sleep
      template:
        metadata:
          labels:
            app: sleep
        spec:
          terminationGracePeriodSeconds: 0
          serviceAccountName: sleep
          containers:
          - name: sleep
            image: curlimages/curl
            command: ["/bin/sleep", "3650d"]
            imagePullPolicy: IfNotPresent
            volumeMounts:
            - mountPath: /etc/sleep/tls
              name: secret-volume
          volumes:
          - name: secret-volume
            secret:
              secretName: sleep-secret
              optional: true
    ---
  3. 通過kubectl串連叢集,分別執行以下命令,在foo命名空間部署httpbin和sleep服務。

    關於如何通過kubectl串連叢集,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集

    kubectl apply -f httpbin.yaml -n foo
    kubectl apply -f sleep.yaml -n foo
  4. 通過sleep服務訪問httpbin服務。

    1. 執行以下命令,進入sleep環境開啟bash。

      kubectl exec -it deploy/sleep -- sh
    2. 執行以下命令,向httpbin服務發送請求。

      curl -I httpbin.foo.svc.cluster.local:8000

      預期輸出:

      HTTP/1.1 200 OK
      server: envoy
      date: Thu, 21 Dec 2023 07:39:55 GMT
      content-type: text/html; charset=utf-8
      content-length: 9593
      access-control-allow-origin: *
      access-control-allow-credentials: true
      x-envoy-upstream-service-time: 14

      返回200 OK,表明請求成功。

步驟二:建立請求身份認證

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇網格資訊安全中心 > 請求身份認證,然後單擊使用YAML建立

  3. 設定命名空間foo,然後在文字框中輸入請求身份認證的YAML內容,單擊建立

    以下YAML表示當請求httpbin服務時,需匹配jwtRules中定義的規則,即要求標頭中如果包含Access Token資訊,解碼後的iss的值必須為testing@secure.istio.iojwks中定義了Token產生的相關資訊。更多資訊,請參見JWT官方文檔

    apiVersion: "security.istio.io/v1beta1"
    kind: "RequestAuthentication"
    metadata:
      name: "jwt-example"
      namespace: foo
    spec:
      selector:
        matchLabels:
          app: httpbin
      jwtRules:
      - issuer: "testing@secure.istio.io"
        jwks: '{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}'
  4. 解析Token。

    本樣本使用的Token資訊如下所示。

    TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg'

    執行以下命令,解析Token。

    echo $TOKEN | cut -d '.' -f2 - | base64 --decode -

    預期輸出:

    {"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}

    JWT官網也提供了同樣的解析Token能力,圖形化輸出如下圖所示。

    JWT

  5. 通過sleep服務訪問httpbin服務。

    1. 執行以下命令,進入sleep環境開啟bash。

      kubectl exec -it deploy/sleep -- sh
    2. 執行以下命令,向httpbin服務發送請求,要求標頭中包含合法的Access Token。

      請將your_valid_access_token_here 替換為實際的合法存取權杖。

      TOKEN=your_valid_access_token_here
      curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000

      預期輸出:

      HTTP/1.1 200 OK
    3. 執行以下命令,向httpbin服務發送請求,要求標頭中包含非法的Access Token。

      請將your_invalid_access_token_here替換為實際的非法存取權杖。

      INVALID_TOKEN=your_invalid_access_token_here
      curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000

      返回401 Unauthorized表示請求被身份認證拒絕,訪問失敗。

步驟三:建立JWT授權策略

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇網格資訊安全中心 > 授權策略,然後單擊使用YAML建立

  3. 設定命名空間foo,然後在文字框中輸入授權策略的YAML內容,單擊建立

    以下YAML表示請求httpbin服務時,只有要求標頭Token解碼後,符合iss的值+/+sub的值(即source.requestPrincipals)為testing@secure.istio.io/testing@secure.istio.io,請求許可權才為ALLOW

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-jwt
      namespace: foo
    spec:
      selector:
        matchLabels:
          app: httpbin
      action: ALLOW
      rules:
      - from:
        - source:
           requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
  4. 解析Token。

    本樣本使用的Token資訊如下所示。

    TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg'

    執行以下命令,解析Token。

    echo $TOKEN | cut -d '.' -f2 - | base64 --decode -

    預期輸出:

    {"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}
  5. 通過sleep服務訪問httpbin服務。

    1. 執行以下命令,進入sleep環境開啟bash。

      kubectl exec -it deploy/sleep -- sh
    2. 執行以下命令,向httpbin服務發送請求,要求標頭中包含合法的Access Token。

      請將your_valid_access_token_here 替換為實際的合法存取權杖。

      TOKEN=your_valid_access_token_here
      curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000

      預期輸出:

      HTTP/1.1 200 OK
    3. 執行以下命令,向httpbin服務發送請求,要求標頭中包含非法的Access Token。

      請將your_invalid_access_token_here替換為實際的非法存取權杖。

      INVALID_TOKEN=your_invalid_access_token_here
      curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000

      返回403 Forbidden表示請求被授權策略拒絕,訪問失敗。

步驟四:追加JWT授權策略

  1. 登入ASM控制台,在左側導覽列,選擇服務網格 > 網格管理

  2. 網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇網格資訊安全中心 > 授權策略

  3. 授權策略頁面,單擊require-jwt策略右側的查看YAML

  4. 編輯對話方塊,補充以下內容,然後單擊確定

        when:
        - key: request.auth.claims[groups]
          values: ["group1"]

    完整的YAML樣本如下。YAML表示請求httpbin服務時,只有要求標頭Token解碼後,符合groups的值包含group1,請求許可權才為ALLOW

    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: require-jwt
      namespace: foo
    spec:
      selector:
        matchLabels:
          app: httpbin
      action: ALLOW
      rules:
      - from:
        - source:
           requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"]
        when:
        - key: request.auth.claims[groups]
          values: ["group1"]
  5. 解析Token。

    本樣本使用的Token資訊如下所示。

    TOKEN_GROUP='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg'

    執行以下命令,解析Token。

    echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode - | jq

    預期輸出:

    {
      "exp": 3537391104,
      "groups": [
        "group1",
        "group2"
      ],
      "iat": 1537391104,
      "iss": "testing@secure.istio.io",
      "scope": [
        "scope1",
        "scope2"
      ],
      "sub": "testing@secure.istio.io"
    }
  6. 通過sleep服務訪問httpbin服務。

    1. 執行以下命令,進入sleep環境開啟bash。

      kubectl exec -it deploy/sleep -- sh
    2. 執行以下命令,向httpbin服務發送請求,要求標頭中包含合法的Access Token。

      請將your_valid_access_token_here替換為實際的合法存取權杖。

      TOKEN=your_valid_access_token_here
      curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000

      返回200 OK表示請求通過授權策略認證,訪問成功。

    3. 執行以下命令,向httpbin服務發送請求,要求標頭中包含非法的Access Token。

      請將your_invalid_access_token_here替換為實際的非法存取權杖。

      INVALID_TOKEN=your_invalid_access_token_here
      curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000

      返回403 Forbidden表示請求被授權策略拒絕,訪問失敗。

相關文檔

如果您想瞭解ASM支援的JWT演算法、如何使用JwksUri、如何配置特定路徑不進行請求的JWT鑒權,請參見JWT FAQ