JWT 토큰

JWT 토큰 (JWT Token)

이 작업은 JSON 웹 토큰(JWT)을 기반으로 접근을 시행하는 Istio 인가 정책을 설정하는 방법을 보여드려요. Istio 인가 정책은 string 및 string 목록 유형의 JWT 클레임을 모두 지원해요.

출처: Istio 문서

본문

이 작업은 JSON 웹 토큰(JWT)을 기반으로 접근을 시행하는 Istio 인가 정책을 설정하는 방법을 보여드려요. Istio 인가 정책은 string 유형과 string 목록 유형의 JWT 클레임을 모두 지원해요.

시작하기 전에 (Before you begin)

이 작업을 시작하기 전에 다음을 수행하세요.

  • Istio 최종 사용자 인증 작업을 완료하세요.
  • Istio 인가 개념을 읽으세요.
  • Istio 설치 가이드를 사용해서 Istio를 설치하세요.
  • 두 워크로드 httpbin과 curl을 배포하세요. 예: foo 네임스페이스에 배포하세요. 두 워크로드 모두 앞에 Envoy 프록시가 있어요. 다음 명령으로 예시 네임스페이스와 워크로드를 배포하세요.
$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/curl/curl.yaml@) -n foo
  • 다음 명령으로 curl이 httpbin과 성공적으로 통신하는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl http://httpbin.foo:8000/ip -sS -o /dev/null -w "%{http_code}\n"
200

[!note] 예상 출력이 안 보이면 몇 초 후에 다시 시도하세요. 캐싱과 전파로 인해 지연이 발생할 수 있어요.

유효한 JWT 및 목록 유형 클레임이 있는 요청 허용하기 (Allow requests with valid JWT and list-typed claims)

  1. 다음 명령은 foo 네임스페이스의 httpbin 워크로드에 대한 jwt-example 요청 인증 정책을 만들어요. httpbin 워크로드에 대한 이 정책은 [email protected]가 발급한 JWT를 수락해요.
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
  name: "jwt-example"
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  jwtRules:
  - issuer: "[email protected]"
    jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.31/security/tools/jwt/samples/jwks.json"
EOF
  1. 잘못된 JWT가 있는 요청이 거부되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer ***" -w "%{http_code}\n"
401
  1. 인가 정책이 없으므로 JWT가 없는 요청이 허용되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -w "%{http_code}\n"
200
  1. 다음 명령은 foo 네임스페이스의 httpbin 워크로드에 대한 require-jwt 인가 정책을 만들어요. 정책은 httpbin 워크로드에 대한 모든 요청이 requestPrincipal이 [email protected]/[email protected]로 설정된 유효한 JWT를 가질 것을 요구해요. Istio는 JWT 토큰의 iss와 sub를 / 구분자로 결합해서 requestPrincipal을 구성해요. 다음과 같이요.
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  name: require-jwt
  namespace: foo
spec:
  selector:
    matchLabels:
      app: httpbin
  action: ALLOW
  rules:
  - from:
    - source:
       requestPrincipals: ["[email protected]/[email protected]"]
EOF
  1. iss와 sub 키를 같은 값 [email protected]로 설정하는 JWT를 가져오세요. 이렇게 하면 Istio가 값 [email protected]/[email protected]로 requestPrincipal 속성을 생성해요.
$ TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.31/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"[email protected]","sub":"[email protected]"}
  1. 유효한 JWT가 있는 요청이 허용되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer ***" -w "%{http_code}\n"
200
  1. JWT가 없는 요청이 거부되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -w "%{http_code}\n"
403
  1. 다음 명령은 require-jwt 인가 정책을 업데이트해서 JWT가 group1 값을 포함하는 groups라는 클레임을 갖도록 요구해요.
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
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"]
EOF

[!note] 클레임 자체에 따옴표가 없는 한 request.auth.claims 필드에 따옴표를 포함하지 마세요.

  1. groups 클레임을 string 목록 group1과 group2로 설정하는 JWT를 가져오세요.
$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.31/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode
{"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"[email protected]","scope":["scope1","scope2"],"sub":"[email protected]"}
  1. groups 클레임에 group1이 포함된 JWT가 있는 요청이 허용되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer ***" -w "%{http_code}\n"
200
  1. groups 클레임이 없는 JWT가 있는 요청이 거부되는지 확인하세요.
$ kubectl exec "$(kubectl get pod -l app=curl -n foo -o jsonpath={.items..metadata.name})" -c curl -n foo -- curl "http://httpbin.foo:8000/headers" -sS -o /dev/null -H "Authorization: Bearer ***" -w "%{http_code}\n"
403

정리 (Clean up)

foo 네임스페이스를 제거하세요.

$ kubectl delete namespace foo

더 알아보기 (Learn more)

  • JWT 인증과 요청 원칙에 대한 자세한 내용은 인증 문서를 참고하세요.
  • 인가 정책의 when 조건과 요청 속성에 대해서는 인가 개념 문서를 참고하세요.