天天看點

基于ASM配置JWT請求授權

前提條件

配置JWT請求授權

環境變量

# ASM執行個體kubeconfig
MESH_CONFIG=
# 使用者ACK執行個體kubeconfig
USER_CONFIG=
# 本地istio路徑
# 可以在https://github.com/istio/istio/releases選擇合适版本下載下傳
ISTIO_HOME=           

1 部署示例服務

1.建立命名空間

foo

,并啟用

istio-injection

基于ASM配置JWT請求授權

2.在命名空間

foo

中,部署官方示例服務

httpbin

sleep

kubectl \
  --kubeconfig "$USER_CONFIG" \
  -n foo \
  apply -f "$ISTIO_HOME"/samples/httpbin/httpbin.yaml

kubectl \
  --kubeconfig "$USER_CONFIG" \
  -n foo \
  apply -f "$ISTIO_HOME"/samples/sleep/sleep.yaml           

3.确認pod就緒前請等待。

kubectl --kubeconfig "$USER_CONFIG" -n foo get po
  
kubectl --kubeconfig "$USER_CONFIG" -n foo wait --for=condition=ready pod -l app=httpbin
kubectl --kubeconfig "$USER_CONFIG" -n foo wait --for=condition=ready pod -l app=sleep           

4.在

sleep

容器内,驗證是否可以請求

httpbin

。期待的結果是

http_code

值為

200

sleep_pod=$(kubectl --kubeconfig "$USER_CONFIG" get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})

RESULT=$(kubectl \
  --kubeconfig "$USER_CONFIG" \
  exec "$sleep_pod" -c sleep -n foo -- curl http://httpbin.foo:8000/ip -s -o /dev/null -w "%{http_code}")

if [[ $RESULT != "200" ]]; then
  echo "http_code($RESULT) should be 200"
  exit
fi           

2. 增加請求認證

1.在命名空間

foo

中,建立RequestAuthentication CRD,建立請求認證:請求

httpbin

服務時,須比對

jwtRules

中定義的規則,即請求頭中如果包含

ACCESS TOKEN

資訊,解碼後

iss

的值須為

[email protected]

jwks

中定義了TOKEN生成的相關資訊,詳見

jwk官方文檔
基于ASM配置JWT請求授權

jwt-example.yaml

:

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

2.驗證請求認證政策生效。請求頭中包含合法的ACCESS TOKEN時傳回狀态碼

200

,否則傳回狀态碼

401

for ((i = 1; i <= 5; i++)); do
    RESULT=$(kubectl \
      --kubeconfig "$USER_CONFIG" \
      exec "$sleep_pod" \
      -c sleep \
      -n foo \
      -- curl "http://httpbin.foo:8000/headers" \
      -s \
      -o /dev/null \
      -H "Authorization: Bearer invalidToken" \
      -w "%{http_code}")
    if [[ $RESULT != "401" ]]; then
      echo "http_code($RESULT) should be 401"
      exit
    fi
done           
for ((i = 1; i <= 10; i++)); do
  RESULT=$(kubectl \
    --kubeconfig "$USER_CONFIG" \
    exec "$sleep_pod" \
    -c sleep \
    -n foo \
    -- curl "http://httpbin.foo:8000/headers" \
    -s \
    -o /dev/null \
    -w "%{http_code}")
  if [[ $RESULT != "200" ]]; then
    echo "http_code($RESULT) should be 200"
    exit
  fi
done           

3. 增加JWT認證政策

1.在命名空間foo中,建立AuthorizationPolicy CRD,建立JWT認證政策:請求

httpbin

服務時,隻有請求頭TOKEN解碼後,符合

iss

的值+

/

+

sub

的值(即

source.requestPrincipals

)為

[email protected]/[email protected]

,請求權限才為

ALLOW

基于ASM配置JWT請求授權

require-jwt.yaml

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["[email protected]/[email protected]"]           

2.TOKEN解析。

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

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

輸出資訊:

{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"[email protected]","sub":"[email protected]"}           
JWT官網

提供了同樣的能力:

基于ASM配置JWT請求授權

3.驗證JWT認證政策生效。請求頭中包含合法的ACCESS TOKEN時傳回狀态碼

200

403

for ((i = 1; i <= 10; i++)); do
    RESULT=$(kubectl \
      --kubeconfig "$USER_CONFIG" \
      exec "$sleep_pod" \
      -c sleep \
      -n foo \
      -- curl "http://httpbin.foo:8000/headers" \
      -s \
      -o /dev/null \
      -H "Authorization: Bearer $TOKEN" \
      -w "%{http_code}")
    if [[ $RESULT != "200" ]]; then
      echo "http_code($RESULT) should be 200"
      exit
    fi
done           
for ((i = 1; i <= 10; i++)); do
    RESULT=$(kubectl \
      --kubeconfig "$USER_CONFIG" \
      exec "$sleep_pod" \
      -c sleep \
      -n foo \
      -- curl "http://httpbin.foo:8000/headers" \
      -s \
      -o /dev/null \
      -w "%{http_code}")
    if [[ $RESULT != "403" ]]; then
      echo "http_code($RESULT) should be 403"
      exit
    fi
done           

4. 追加JWT認證政策

1.在命名空間foo中,更新JWT認證政策

require-jwt

,增加規則:請求

httpbin

groups

的值包含

group1

ALLOW

require-jwt-group.yaml

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["[email protected]/[email protected]"]
    when:
    - key: request.auth.claims[groups]
      values: ["group1"]           
TOKEN_GROUP='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg'

echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode - | jq           
{
  "exp": 3537391104,
  "groups": [
    "group1",
    "group2"
  ],
  "iat": 1537391104,
  "iss": "[email protected]",
  "scope": [
    "scope1",
    "scope2"
  ],
  "sub": "[email protected]"
}           

200

403

for ((i = 1; i <= 10; i++)); do
    RESULT=$(kubectl \
      --kubeconfig "$USER_CONFIG" \
      exec "$sleep_pod" \
      -c sleep \
      -n foo \
      -- curl "http://httpbin.foo:8000/headers" \
      -s \
      -o /dev/null \
      -H "Authorization: Bearer $TOKEN_GROUP" \
      -w "%{http_code}")
    if [[ $RESULT != "200" ]]; then
      echo "http_code($RESULT) should be 200"
      exit
    fi
done           
for ((i = 1; i <= 10; i++)); do
    RESULT=$(kubectl \
      --kubeconfig "$USER_CONFIG" \
      exec "$sleep_pod" \
      -c sleep \
      -n foo \
      -- curl "http://httpbin.foo:8000/headers" \
      -s \
      -o /dev/null \
      -H "Authorization: Bearer $TOKEN" \
      -w "%{http_code}")
    if [[ $RESULT != "403" ]]; then
      echo "http_code($RESULT) should be 200"
      exit
    fi
done