JWT 클레임 기반 라우팅
JWT 클레임 기반 라우팅 (JWT claim based routing)
이 작업은 요청 인증(request authentication)과 가상 서비스(virtual service)를 사용해서 Istio 인그레스 게이트웨이에서 JWT 클레임을 기반으로 요청을 라우팅하는 방법을 보여드려요. 이 기능은 개발자/고급 사용자를 대상으로 하며 Alpha 단계로 간주돼요.
출처: Istio 문서
본문
[!note] 이 기능은 개발자/고급 사용자를 대상으로 하며 Alpha 단계로 간주돼요. 이 작업은 요청 인증과 가상 서비스를 사용해서 Istio 인그레스 게이트웨이에서 JWT 클레임을 기반으로 요청을 라우팅하는 방법을 보여드려요. 참고: 이 기능은 Istio 인그레스 게이트웨이만 지원하며, JWT 클레임을 제대로 검증하고 라우팅하려면 요청 인증과 가상 서비스 모두를 사용해야 해요.
시작하기 전에 (Before you begin)
- Istio 인증 정책과 가상 서비스 개념을 이해하세요.
- Istio 설치 가이드를 사용해서 Istio를 설치하세요.
foo같은 네임스페이스에httpbin이라는 워크로드를 배포하고, 다음 명령으로 Istio 인그레스 게이트웨이를 통해 노출하세요.
$ kubectl create ns foo
$ kubectl apply -f <(istioctl kube-inject -f @samples/httpbin/httpbin.yaml@) -n foo
$ kubectl apply -f @samples/httpbin/httpbin-gateway.yaml@ -n foo
- 인그레스 IP와 포트 확인하기 지침을 따라
INGRESS_HOST와INGRESS_PORT환경 변수를 정의하세요. httpbin워크로드와 인그레스 게이트웨이가 예상대로 동작하는지 다음 명령으로 확인하세요.
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n"
200
[!note] 예상 출력이 안 보이면 몇 초 후에 다시 시도하세요. 캐싱과 전파 오버헤드로 인해 지연이 발생할 수 있어요.
JWT 클레임 기반 인그레스 라우팅 구성하기 (Configuring ingress routing based on JWT claims)
Istio 인그레스 게이트웨이는 인증된 JWT를 기반으로 하는 라우팅을 지원해요. 이는 최종 사용자 신원 기반 라우팅에 유용하며, 인증되지 않은 HTTP 속성(예: 경로나 헤더)을 사용하는 것보다 더 안전해요.
- JWT 클레임을 기반으로 라우팅하려면 먼저 JWT 검증을 활성화하는 요청 인증을 만드세요.
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1
kind: RequestAuthentication
metadata:
name: ingress-jwt
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: "[email protected]"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.31/security/tools/jwt/samples/jwks.json"
EOF
요청 인증은 Istio 인그레스 게이트웨이에서 JWT 검증을 활성화해서, 나중에 가상 서비스에서 검증된 JWT 클레임을 라우팅 목적으로 사용할 수 있게 해줘요. JWT 클레임 기반 라우팅은 인그레스 게이트웨이에서만 지원되므로 요청 인증은 인그레스 게이트웨이에 적용돼요. 참고: 요청 인증은 요청에 JWT가 존재할 때만 확인해요. JWT를 필수로 만들고 요청에 JWT가 없으면 거부하려면 이 작업에서 지정한 인가 정책을 적용하세요. 2. 검증된 JWT 클레임을 기반으로 라우팅하도록 가상 서비스를 업데이트하세요.
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: httpbin
namespace: foo
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /headers
headers:
"@request.auth.claims.groups":
exact: group1
route:
- destination:
port:
number: 8000
host: httpbin
EOF
가상 서비스는 예약된 헤더 "@request.auth.claims.groups"를 사용해서 JWT 클레임 groups와 매칭해요. 접두사 @는 HTTP 헤더가 아니라 JWT 검증에서 파생된 메타데이터와 매칭한다는 뜻이에요. string, string 목록, 중첩 클레임 유형이 지원돼요. 중첩 클레임 이름의 구분자로 . 또는 []를 사용하세요. 예를 들어 "@request.auth.claims.name.givenName" 또는 "@request.auth.claims[name][givenName]"은 중첩 클레임 name과 givenName을 매칭하며, 여기서는 동등해요. 클레임 이름에 .이 포함되면 []만 구분자로 사용할 수 있어요.
JWT 클레임 기반 인그레스 라우팅 검증하기 (Validating ingress routing based on JWT claims)
- JWT 없이 인그레스 게이트웨이가 HTTP 코드 404를 반환하는지 검증하세요.
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers"
HTTP/1.1 404 Not Found
...
JWT가 없을 때 요청을 명시적으로 HTTP 코드 403으로 거부하는 인가 정책을 만들 수도 있어요. 2. 잘못된 JWT로 인그레스 게이트웨이가 HTTP 코드 401을 반환하는지 검증하세요.
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer some.i...oken"
HTTP/1.1 401 Unauthorized
...
JWT가 검증에 실패했기 때문에 401은 요청 인증에 의해 반환돼요.
3. 클레임 groups: group1이 포함된 유효한 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]"}
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer ***"
HTTP/1.1 200 OK
...
- 유효한 JWT지만 클레임
groups: group1이 포함되지 않은 경우 인그레스 게이트웨이가 HTTP 코드 404를 반환하는지 검증하세요.
$ TOKEN_NO_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.31/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN_NO_GROUP" | cut -d '.' -f2 - | base64 --decode
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"[email protected]","sub":"[email protected]"}
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer ***"
HTTP/1.1 404 Not Found
...
정리 (Cleanup)
foo네임스페이스를 제거하세요.
$ kubectl delete namespace foo
- 요청 인증을 제거하세요.
$ kubectl delete requestauthentication ingress-jwt -n istio-system
더 알아보기 (Learn more)
- 요청 인증 정책과 JWT 규칙에 대한 자세한 내용은 인증 정책 문서를 참고하세요.
- 가상 서비스의 헤더 매칭과 라우팅 규칙에 대해서는 트래픽 관리 문서를 참고하세요.