當您需要在服務網格中驗證和授權HTTP請求來源時,可以配置JWT(JSON Web Token)請求鑒權,實現來源認證(最終用戶認證)。在處理請求時,該配置能夠準確核實請求頭中Access Token的有效性,只允許來源可信的請求訪問服務,提高服務的安全性,并簡化服務間身份驗證的復雜性。
前提條件
已添加集群到ASM實例,且ASM實例版本為1.6及以上。
背景信息
服務網格包含兩種認證方式:
傳輸認證:基于雙向TLS技術,常用于服務間通信認證。
來源認證:基于JWT技術,常用于客戶端和服務之間的請求認證。
JWT是一種用于雙方之間傳遞安全信息的表述性聲明規范。關于JWT的更多信息,請參見JWT官方文檔。
步驟一:創建命名空間并部署示例服務
創建foo命名空間,設置標簽名稱為istio-injection,值為enabled。具體操作,請參見管理全局命名空間。
使用以下內容,創建httpbin.yaml和sleep.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
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 ---
通過kubectl連接集群,分別執行以下命令,在foo命名空間部署httpbin和sleep服務。
關于如何通過kubectl連接集群,請參見獲取集群KubeConfig并通過kubectl工具連接集群。
kubectl apply -f httpbin.yaml -n foo kubectl apply -f sleep.yaml -n foo
通過sleep服務訪問httpbin服務。
執行以下命令,進入sleep環境開啟bash。
kubectl exec -it deploy/sleep -- sh
執行以下命令,向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
,表明請求成功。
步驟二:創建請求身份認證
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 ,然后單擊使用YAML創建。
設置命名空間為foo,然后在文本框中輸入請求身份認證的YAML內容,單擊創建。
以下YAML表示當請求
httpbin
服務時,需匹配jwtRules
中定義的規則,即請求頭中如果包含Access Token信息,解碼后的iss
的值必須為testing@secure.istio.io
。jwks
中定義了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"}]}'
解析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能力,圖形化輸出如下圖所示。
通過sleep服務訪問httpbin服務。
執行以下命令,進入sleep環境開啟bash。
kubectl exec -it deploy/sleep -- sh
執行以下命令,向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
執行以下命令,向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授權策略
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 ,然后單擊使用YAML創建。
設置命名空間為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"]
解析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"}
通過sleep服務訪問httpbin服務。
執行以下命令,進入sleep環境開啟bash。
kubectl exec -it deploy/sleep -- sh
執行以下命令,向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
執行以下命令,向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授權策略
登錄ASM控制臺,在左側導航欄,選擇 。
在網格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在授權策略頁面,單擊require-jwt策略右側的查看YAML。
在編輯對話框,補充以下內容,然后單擊確定。
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"]
解析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" }
通過sleep服務訪問httpbin服務。
執行以下命令,進入sleep環境開啟bash。
kubectl exec -it deploy/sleep -- sh
執行以下命令,向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
表示請求通過授權策略認證,訪問成功。執行以下命令,向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。