Ssoon

[5주차] 마이크로서비스 통신 보안 : 최종 사용자 인증 및 권한 부여 본문

Istio Hands-on Study [1기]

[5주차] 마이크로서비스 통신 보안 : 최종 사용자 인증 및 권한 부여

구구달스 2025. 4. 22. 10:30

🔒 Istio를 활용한
End-User 인증과 권한 부여


🛡️ End-User 인증과 JWT의 역할

Istio는 서비스 간 통신뿐만 아니라 최종 사용자(end-user)의 인증과 권한 부여를 지원합니다. 이를 위해 JWT를 사용하며, JWT는 클라이언트의 신원을 확인하고 권한을 부여하는 데 중요한 역할을 합니다. JWT는 컴팩트한 형태로 사용자 정보를 전달하며, Istio는 이를 활용해 보안 정책을 적용합니다.

  • JWT는 클라이언트의 신원과 권한 정보를 포함하여, Istio가 이를 검증하고 정책을 적용하도록 돕습니다.
Istio는 JWT를 사용해 end-user 인증과 권한 부여를 구현하며,
보안 정책 적용을 지원합니다.

📜 JSON Web Token(JWT)이란?

  • JWT는 클라이언트와 서버 간 인증을 위해 사용되는 컴팩트한 claims 표현 형식입니다.
    JWT는 세 가지 주요 부분으로 구성되며, 각 부분은 점(.)으로 구분되고 Base64 URL로 인코딩됩니다. 이는 HTTP 요청에 적합하게 설계되었습니다.
  • JWT의 구성 요소는 다음과 같습니다:
    • Header: 토큰의 유형(JWT)과 사용된 해싱 알고리즘(예: RS256)을 포함합니다.
    • Payload: 사용자 정보(claims)를 포함하며, 예를 들어 사용자의 그룹이나 만료 시간이 들어갑니다.
    • Signature: JWT의 진위 여부를 확인하기 위한 서명으로, 토큰의 무결성을 보장합니다

  • JWT는 Header, Payload, Signature로 구성되며, 각 부분은 Base64 URL로 인코딩되어 점(.)으로 연결됩니다.
JWT는 Header, Payload, Signature로 구성된 컴팩트한 토큰으로,
클라이언트 인증에 사용됩니다.

🔍 JWT의 실제 예시

  •  JWT(JSON Web Token) 관련 도구를 설치
$ sudo apt install jwt
[sudo] password for ssoon:
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following NEW packages will be installed:
  jwt
0 upgraded, 1 newly installed, 0 to remove and 86 not upgraded.
Need to get 1222 kB of archives.
...
  • JWT의 예시 토큰을 살펴보겠습니다.
    아래는 ./ch9/enduser/user.jwt 파일에 포함된 토큰을 jwt-cli 유틸리티(https://github.com/mike-engel/jwt-cli)로 디코딩한 결과입니다.
$ cat ./ch9/enduser/user.jwt | jwt -show -
Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}
Claims:
{
    "exp": 4745145038,
    "group": "user",
    "iat": 1591545038,
    "iss": "auth@istioinaction.io",
    "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
}

Token Header

Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}

Token Claims (Payload)

Claims:
{
    "exp": 4745145038,
    "group": "user",
    "iat": 1591545038,
    "iss": "auth@istioinaction.io",
    "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
}
  • exp: 토큰의 만료 시간(expiration time)을 나타냅니다.
  • group: 사용자가 속한 그룹(여기서는 user)을 나타내는 클레임입니다.
  • iat: 토큰 발급 시간(issued at)을 나타냅니다.
  • iss: 토큰 발급자(issuer), 여기서는 testing@secure.istio.io입니다.
  • sub: 토큰의 주체(subject), 즉 사용자의 고유 식별자입니다.
  • 이 클레임들은 서비스가 클라이언트의 신원과 권한을 판단하는 데 사용됩니다. 예를 들어, group: user 클레임을 통해 서비스는 해당 사용자가 user 그룹에 속해 있음을 확인하고, 적절한 접근 수준을 부여할 수 있습니다.
JWT의 Payload는 사용자 신원과 권한 정보를 포함하며,
서비스는 이를 기반으로 접근을 제어합니다.

🔐 JWT 발급 및 검증 과정

  • JWT는 신뢰할 수 있는 인증 서버에서 발급되며, 검증 과정을 통해 무결성과 진위 여부가 확인됩니다. 이 과정은 다음과 같이 진행됩니다:
    • 발급: 인증 서버는 private key를 사용해 JWT에 서명을 추가합니다. 이 서명은 토큰의 무결성을 보장합니다.
    • 검증: 서버는 public key를 사용해 서명을 검증합니다. 이 공용 키는 JWKS(JSON Web Key Set)라는 형태로, 잘 알려진 HTTP 엔드포인트에서 제공됩니다.

JWKS의 역할

  • JWKS인증 서버의 공용 키를 포함하며, 서비스는 이를 가져와 JWT의 서명을 검증합니다.
  • 검증 과정에서는 서명을 복호화하여 토큰 데이터의 해시와 비교합니다. 일치하면 토큰이 신뢰할 수 있는 것으로 간주됩니다.

  • 서버는 JWKS에서 공용 키를 가져와 JWT의 서명을 검증하고, 토큰의 신뢰성을 확인합니다.
JWT는 인증 서버에서 발급되고,
JWKS의 공용 키를 통해 검증되어 신뢰성을 보장합니다.

🚀 인증 서버 구현 옵션

  • 인증 서버를 설정해 JWT를 발급하고 검증하는 방법에는 여러 가지가 있습니다:
    • 애플리케이션 백엔드: 애플리케이션 프레임워크 내에서 인증 서버를 구현할 수 있습니다.
    • 독립 서비스: OpenIAM(openiam.com) 또는 Keycloak(keycloak.org) 같은 전용 인증 서비스를 사용할 수 있습니다.
    • Identity-as-a-Service: Auth0(auth0.com), Okta(okta.com) 같은 클라우드 기반 인증 솔루션을 활용할 수 있습니다.
  • 이러한 옵션은 애플리케이션의 요구사항과 인프라에 따라 선택할 수 있습니다.
인증 서버는 애플리케이션 백엔드, 독립 서비스,
또는 Identity-as-a-Service로 구현할 수 있습니다.

📌 핵심 요약

  • End-User 인증: Istio는 JWT를 사용해 end-user 인증과 권한 부여를 지원합니다.
  • JWT 구조: Header, Payload, Signature로 구성되며, Base64 URL로 인코딩되어 HTTP 요청에 적합합니다.
  • JWT 클레임: Payload의 클레임(예: group, exp, iss, sub)은 사용자 신원과 권한을 정의합니다.
  • 발급 및 검증: 인증 서버는 private key로 JWT를 발급하고, JWKS의 public key로 검증합니다.
  • 인증 서버 옵션: 애플리케이션 백엔드, OpenIAM/Keycloak, Auth0/Okta 같은 솔루션으로 인증 서버를 구축할 수 있습니다.

🔒 Istio Ingress Gateway에서
End-User 인증과 권한 부여

Istio는 JWT(JSON Web Token)를 사용해 end-user의 인증과 권한 부여를 지원하며, 특히 ingress gateway에서 이를 처리하는 것이 일반적입니다.


🛡️ Ingress Gateway에서의 End-User 인증

End-user identity provider에서 인증을 받아 JWT를 발급받은 사용자를 의미합니다. 이 JWT는 사용자의 신원과 권한 정보를 포함합니다. Istio 워크로드는 이 JWT를 검증하여 요청을 인증하고 권한을 부여할 수 있습니다.

이 기능은 모든 워크로드에서 수행할 수 있지만, ingress gateway에서 처리하는 것이 일반적입니다. 그 이유는 다음과 같습니다:

  • 성능 향상: 유효하지 않은 요청을 초기에 차단하여 후속 서비스의 부담을 줄입니다.
  • 보안 강화: JWT를 요청에서 제거(redact)하여, 후속 서비스에서 JWT가 유출되거나 재사용(replay attack)되는 것을 방지합니다.
Ingress Gateway에서 JWT 기반 end-user 인증을 처리하면
성능과 보안이 향상됩니다.

🧹 작업 환경 초기화

  • RequestAuthentication 설정을 시작하기 전에, 기존 리소스를 정리하고 새로운 환경을 준비해야 합니다.
    아래 명령어를 사용해 istioinaction 네임스페이스의 기존 리소스를 모두 삭제합니다.
$ kubectl delete virtualservice,deployment,service,\
destinationrule,gateway,peerauthentication,authorizationpolicy --all -n istioinaction
virtualservice.networking.istio.io "webapp-virtualservice" deleted
deployment.apps "catalog" deleted
deployment.apps "webapp" deleted
service "catalog" deleted
service "webapp" deleted
gateway.networking.istio.io "coolstore-gateway" deleted
peerauthentication.security.istio.io "webapp" deleted
authorizationpolicy.security.istio.io "catalog-viewer" deleted
authorizationpolicy.security.istio.io "webapp-allow-unauthenticated-view-default-ns" deleted
authorizationpolicy.security.istio.io "webapp-allow-view-default-ns" deleted
  • 이 과정을 통해 깨끗한 환경에서 실습을 시작할 수 있습니다.
기존 리소스를 삭제하여 새로운 환경을 준비합니다.

🚀 샘플 워크로드 설정

  • 환경 초기화 후, 실습에 필요한 샘플 워크로드를 배포합니다. 아래 명령어로 catalog와 webapp 서비스를 배포합니다.
$ kubectl apply -f services/catalog/kubernetes/catalog.yaml -n istioinaction
serviceaccount/catalog unchanged
service/catalog created
deployment.apps/catalog created

$ kubectl apply -f services/webapp/kubernetes/webapp.yaml -n istioinaction
serviceaccount/webapp unchanged
service/webapp created
deployment.apps/webapp created
  • catalog.yaml: catalog 서비스를 배포합니다.
  • webapp.yaml: webapp 서비스를 배포합니다.
  • 이 워크로드는 ingress gateway를 통해 들어오는 트래픽을 처리할 준비를 합니다.
catalog와 webapp 워크로드를 배포하여
실습 환경을 구성합니다.

🌐 Ingress Gateway와 VirtualService 설정

  • RequestAuthentication을 설정하기 전에, 트래픽이 Istio ingress gateway를 통해 들어오도록 Gateway와 VirtualService 리소스를 설정해야 합니다. 이는 트래픽을 webapp 서비스로 라우팅하는 역할을 합니다.
    아래 명령어로 관련 리소스를 배포합니다:
$ kubectl apply -f ch9/enduser/ingress-gw-for-webapp.yaml -n istioinaction
gateway.networking.istio.io/webapp-gateway created
virtualservice.networking.istio.io/webapp-virtualservice created
  • Gateway: 외부 트래픽이 ingress gateway로 들어오도록 허용합니다.
  • VirtualService: 들어온 트래픽을 webapp 서비스로 라우팅합니다.
  • 이 설정은 RequestAuthentication 실습을 위한 기반 환경을 완성합니다.
Gateway와 VirtualService를 설정하여
트래픽이 ingress gateway를 통해 webapp으로 라우팅되도록 합니다.

 


🔐 RequestAuthentication 준비

  • 이제 워크로드와 트래픽 라우팅 설정이 완료되었으므로, RequestAuthentication 리소스를 사용해 JWT 기반 인증을 설정할 준비가 되었습니다. 다음 섹션에서는 RequestAuthentication의 구체적인 설정 방법과 동작 원리를 다룰 것입니다.

핵심 내용: 환경 설정 완료 후, RequestAuthentication을 통해 JWT 인증을 설정할 준비가 되었습니다.


📌 핵심 요약

  • End-User 인증: Istio는 JWT를 사용해 end-user 인증과 권한 부여를 지원하며, ingress gateway에서 처리하는 것이 효율적입니다.
  • Ingress Gateway의 장점: 유효하지 않은 요청을 초기에 차단하고 JWT를 제거하여 성능과 보안을 강화합니다.
  • 환경 초기화: 기존 리소스를 삭제하여 깨끗한 환경을 준비합니다.
  • 워크로드 배포: catalog webapp 서비스를 배포하여 실습 환경을 구성합니다.
  • Gateway와 VirtualService: 트래픽을 ingress gateway를 통해 webapp으로 라우팅하도록 설정합니다.

🔒 Istio RequestAuthentication으로
JWT 검증하기

Istio의 RequestAuthentication 리소스는 JWT(JSON Web Token)를 검증하고, 유효한 토큰의 claims를 추출해 filter metadata에 저장합니다. 이를 통해 AuthorizationPolicy가 사용자 신원에 따라 요청을 허용하거나 거부할 수 있습니다.


🛡️ RequestAuthentication의 역할

RequestAuthentication ingress gateway에서 JWT를 검증하는 핵심 리소스입니다. 주요 기능은 다음과 같습니다:

  • JWT 검증: 토큰의 유효성을 확인합니다.
  • Claims 추출: 유효한 토큰의 claims(예: group: admin)를 추출합니다.
  • Filter Metadata 저장: 추출된 claims filter metadata에 저장하여 AuthorizationPolicy에서 사용할 수 있게 합니다.

Filter metadata는 서비스 프록시가 요청을 처리하는 동안 필터 간에 공유되는 키-값 쌍입니다. 예를 들어, group: admin 클레임이 포함된 요청이 검증되면, 이 정보가 filter metadata에 저장되어 권한 정책에서 활용됩니다.

RequestAuthentication은
JWT를 검증하고 claims를 filter metadata에 저장해 권한 부여를 지원합니다.


📊 JWT 요청의 세 가지 결과

RequestAuthentication은 요청의 JWT 유무와 유효성에 따라 세 가지 결과를 생성합니다:

  1. 유효한 토큰: 토큰이 유효하면 요청이 클러스터에 허용되고, claims filter metadata에 저장됩니다.
  2. 유효하지 않은 토큰: 토큰이 유효하지 않으면 요청이 거부됩니다.
  3. 토큰 없는 요청: 토큰이 없으면 요청이 클러스터에 허용되지만, request identity가 없으므로 claims filter metadata에 저장되지 않습니다.
RequestAuthentication은 JWT 검증만 담당하며,
권한 부여는 AuthorizationPolicy가 처리합니다.

📜 RequestAuthentication 리소스 생성

  • 다음은 ingress gateway에서 auth@istioinaction.io 발급자의 토큰을 검증하도록 설정한 RequestAuthentication 리소스입니다.
$ cat ch9/enduser/jwt-token-request-authn.yaml
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
  name: "jwt-token-request-authn"
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  jwtRules:
  - issuer: "auth@istioinaction.io" #JWT 토큰을 발급한 주체를 지정
    jwks: | #JWT를 검증할 때 사용할 공개 키들을 담고 있는 JSON 형식
      { "keys":[ {"e":"AQAB","kid":"CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM","kty":"RSA","n":"zl9VRDbmVvyXNdyoGJ5uhuTSRA2653KHEi3XqITfJISvedYHVNGoZZxUCoiSEumxqrPY_Du7IMKzmT4bAuPnEalbY8rafuJNXnxVmqjTrQovPIerkGW5h59iUXIz6vCznO7F61RvJsUEyw5X291-3Z3r-9RcQD9sYy7-8fTNmcXcdG_nNgYCnduZUJ3vFVhmQCwHFG1idwni8PJo9NH6aTZ3mN730S6Y1g_lJfObju7lwYWT8j2Sjrwt6EES55oGimkZHzktKjDYjRx1rN4dJ5PR5zhlQ4kORWg1PtllWy1s5TSpOUv84OPjEohEoOWH0-g238zIOYA83gozgbJfmQ"}]}
  • selector: 정책이 적용될 워크로드를 지정합니다. 여기서는 istio-ingressgateway에 적용됩니다.
  • issuer: 기대하는 토큰 발급자를 정의합니다(여기서는 auth@istioinaction.io).
  • jwks: 토큰 검증에 사용할 공용 키(JSON Web Key Set)를 정의합니다.

  • 이 리소스를 클러스터에 적용하려면 다음 명령어를 실행합니다:
$ kubectl apply -f ch9/enduser/jwt-token-request-authn.yaml
requestauthentication.security.istio.io/jwt-token-request-authn created
RequestAuthentication 리소스는 ingress gateway에서
특정 발급자의 JWT를 검증하도록 설정합니다.

✅ 유효한 토큰 요청 테스트

  • 유효한 JWT(ch9/enduser/user.jwt)를 사용해 요청을 테스트해 보겠습니다.
$ cat ch9/enduser/user.jwt
eyJhbGciOiJSUzI1NiIsImtpZCI6IkNVLUFESkpFYkg5YlhsMHRwc1FXWXVvNEV3bGt4RlVIYmVKNGNra2FrQ00iLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ3NDUxNDUwMzgsImdyb3VwIjoidXNlciIsImlhdCI6MTU5MTU0NTAzOCwiaXNzIjoiYXV0aEBpc3Rpb2luYWN0aW9uLmlvIiwic3ViIjoiOWI3OTJiNTYtN2RmYS00ZTRiLWE4M2YtZTIwNjc5MTE1ZDc5In0.jNDoRx7SNm8b1xMmPaOEMVgwdnTmXJwD5jjCH9wcGsLisbZGcR6chkirWy1BVzYEQDTf8pDJpY2C3H-aXN3IlAcQ1UqVe5lShIjCMIFTthat3OuNgu-a91csGz6qtQITxsOpMcBinlTYRsUOICcD7UZcLugxK4bpOECohHoEhuASHzlH-FYESDB-JYrxmwXj4xoZ_jIsdpuqz_VYhWp8e0phDNJbB6AHOI3m7OHCsGNcw9Z0cks1cJrgB8JNjRApr9XTNBoEC564PX2ZdzciI9BHoOFAKx4mWWEqW08LDMSZIN5Ui9ppwReSV2ncQOazdStS65T43bZJwgJiIocSCg

$ USER_TOKEN=$(< ch9/enduser/user.jwt)

$ echo "$USER_TOKEN" | jwt -show -
Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}
Claims:
{
    "exp": 4745145038,
    "group": "user",
    "iat": 1591545038,
    "iss": "auth@istioinaction.io",
    "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
    
    
$ curl -H "Authorization: Bearer $USER_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog
200
}
  • 응답 코드 200은 인증이 성공했음을 나타냅니다. 현재 AuthorizationPolicy가 없으므로 요청이 기본적으로 허용됩니다.
유효한 JWT를 포함한 요청은 인증 후 클러스터에 허용됩니다.

❌ 유효하지 않은 토큰 요청 테스트

  • 유효하지 않은 발급자(old-auth@istioinaction.io)의 토큰(ch9/enduser/not-configured-issuer.jwt)으로 요청을 테스트합니다.
$ cat ch9/enduser/not-configured-issuer.jwt
eyJhbGciOiJSUzI...

$ WRONG_ISSUER=$(< ch9/enduser/not-configured-issuer.jwt)

$ echo "$WRONG_ISSUER" | jwt -show -
Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}
Claims:
{
    "exp": 4745151548,
    "group": "user",
    "iat": 1591551548,
    "iss": "old-auth@istioinaction.io",
    "sub": "79d7506c-b617-46d1-bc1f-f511b5d30ab0"
}

$ curl -H "Authorization: Bearer $WRONG_ISSUER" \
     -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog
401
  • 요청이 실패하며, 오류 메시지는 토큰의 발급자가 설정되지 않았음을 나타냅니다.
유효하지 않은 발급자의 토큰은 
RequestAuthentication에 의해 거부됩니다.

🌐 토큰 없는 요청 테스트

  • 토큰 없이 요청을 보냅니다.
$ curl -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/cataloglog
200
  • 응답 코드 200은 요청이 클러스터에 허용되었음을 보여줍니다. 이는 RequestAuthentication이 토큰 없는 요청을 기본적으로 허용하기 때문입니다. 하지만 이는 보안상 문제가 될 수 있으므로, 토큰 없는 요청을 차단하려면 추가 설정이 필요합니다.
토큰 없는 요청은 기본적으로 허용되지만,
보안을 위해 차단할 수 있습니다.

🚫 토큰 없는 요청 차단

  • 토큰 없는 요청을 차단하려면 AuthorizationPolicy를 사용해 requestPrincipals가 없는 요청을 명시적으로 거부해야 합니다.
$ cat ch9/enduser/app-gw-requires-jwt.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: app-gw-requires-jwt
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway #istio-ingressgateway라는 라벨을 가진 워크로드에 적용
  action: DENY #조건에 일치하는 요청은 거부됩니다.
  rules:
  - from:
    - source:
        notRequestPrincipals: ["*"] #JWT 발급자 정보가 없는 요청을 대상
    to:
    - operation:
        hosts: ["webapp.istioinaction.io:30000"] 
        #대상 호스트가 webapp.istioinaction.io:30000 인 경우에만 DENY가 적용
  • notRequestPrincipals: ["*"]: requestPrincipals가 없는 모든 요청을 매칭합니다.
  • action: DENY: 매칭된 요청을 거부합니다.
  • hosts: 특정 호스트(webapp.istioinaction.io)에만 적용됩니다.
  • requestPrincipals는 JWT의 issuer와 subject 클레임을 결합한 형태(iss/sub)로, RequestAuthentication에서 검증된 후 filter metadata에 저장됩니다.
    이 리소스를 적용합니다:
$ kubectl apply -f ch9/enduser/app-gw-requires-jwt.yaml
Warning: configured AuthorizationPolicy will deny all traffic to TCP ports under its scope due to the use of only HTTP attributes in a DENY rule; it is recommended to explicitly specify the port
authorizationpolicy.security.istio.io/app-gw-requires-jwt created
  • 이제 토큰 없는 요청을 다시 테스트합니다:
$ curl -sSl -o /dev/null -w "%{http_code}" webapp.istioinaction.io:30000/api/catalog
403
  • 응답 코드 403은 요청이 거부되었음을 나타냅니다. 이제 토큰 없는 요청이 차단됩니다.
AuthorizationPolicy를 사용해
토큰 없는 요청을 차단하여 보안을 강화할 수 있습니다.

🔐 JWT 클레임 기반 접근 제어

  • 다양한 사용자에게 서로 다른 접근 수준을 부여하려면, JWT의 claims를 기반으로 AuthorizationPolicy를 설정할 수 있습니다.
    예를 들어, 일반 사용자(group: user)는 읽기(GET)만 허용하고, 관리자(group: admin)는 모든 작업을 허용하도록 설정해 보겠습니다.
# 일반 사용자 토큰 : 'group: user' 클레임
$ cat ch9/enduser/user.jwt | jwt -show -
Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}
Claims:
{
    "exp": 4745145038,
    "group": "user",
    "iat": 1591545038,
    "iss": "auth@istioinaction.io",
    "sub": "9b792b56-7dfa-4e4b-a83f-e20679115d79"
}

# 관리자 토큰 : 'group: admin' 클레임
$ cat ch9/enduser/admin.jwt | jwt -show -
Header:
{
    "alg": "RS256",
    "kid": "CU-ADJJEbH9bXl0tpsQWYuo4EwlkxFUHbeJ4ckkakCM",
    "typ": "JWT"
}
Claims:
{
    "exp": 4745145071,
    "group": "admin",
    "iat": 1591545071,
    "iss": "auth@istioinaction.io",
    "sub": "218d3fb9-4628-4d20-943c-124281c80e7b"
}

일반 사용자 정책

  • 일반 사용자가 webapp의 읽기 요청(GET)을 수행할 수 있도록 설정합니다.
$ cat ch9/enduser/allow-all-with-jwt-to-webapp.yaml
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-all-with-jwt-to-webapp
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["auth@istioinaction.io/*"]
    to:
    - operation:
      hosts: ["webapp.istioinaction.io:30000"]
        methods: ["GET"]

관리자 정책

  • 관리자가 모든 작업을 수행할 수 있도록 설정합니다.
$ cat ch9/enduser/allow-mesh-all-ops-admin.yaml
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "allow-mesh-all-ops-admin"
  namespace: istio-system
spec:
  selector:
    matchLabels:
      app: istio-ingressgateway
  action: ALLOW
  rules:
  - from:
    - source:
        requestPrincipals: ["auth@istioinaction.io/*"]
    when:
    - key: request.auth.claims[group]
      values: ["admin"]
  • action: ALLOW는 생략되었으며, 기본값으로 적용됩니다.
  • when: group 클레임이 admin인 경우에만 정책을 적용합니다.
  • 이 리소스들을 클러스터에 적용합니다:
$ kubectl apply -f ch9/enduser/allow-all-with-jwt-to-webapp.yaml
authorizationpolicy.security.istio.io/allow-all-with-jwt-to-webapp created

$ kubectl apply -f ch9/enduser/allow-mesh-all-ops-admin.yaml
authorizationpolicy.security.istio.io/allow-mesh-all-ops-admin created

일반 사용자 테스트

  • 일반 사용자 토큰(ch9/enduser/user.jwt)으로 읽기 요청을 테스트합니다:
$ USER_TOKEN=$(< ch9/enduser/user.jwt)

$ curl -H "Authorization: Bearer $USER_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}\n" webapp.istioinaction.io:30000/api/catalog
200
  • 결과: 200 => 읽기 요청은 성공합니다. 하지만 쓰기 요청(POST)은 실패합니다:
$ curl -H "Authorization: Bearer $USER_TOKEN" \
     -XPOST webapp.istioinaction.io:30000/api/catalog \
     --data '{"id": 2, "name": "Shoes", "price": "84.00"}'
RBAC: access denied

관리자 테스트

  • 관리자 토큰(ch9/enduser/admin.jwt)으로 쓰기 요청을 테스트합니다:
$ ADMIN_TOKEN=$(< ch9/enduser/admin.jwt)

$ curl -H "Authorization: Bearer $ADMIN_TOKEN" \
     -sSl -o /dev/null -w "%{http_code}\n" webapp.istioinaction.io:30000/api/catalog
200
  • 결과: 200 => 관리자는 쓰기 요청이 허용됩니다.
JWT claims를 기반으로 사용자별 접근 수준을 세밀하게 제어할 수 있습니다.

📌 핵심 요약

  • RequestAuthentication의 역할: JWT를 검증하고 claims filter metadata에 저장하여 AuthorizationPolicy와 연동됩니다.
  • 요청 결과: 유효한 토큰은 허용, 유효하지 않은 토큰은 거부, 토큰 없는 요청은 claims 없이 허용됩니다.
  • 리소스 설정: ingress gateway에서 특정 발급자의 JWT를 검증하도록 RequestAuthentication을 설정합니다.
  • 토큰 없는 요청 차단: AuthorizationPolicy notRequestPrincipals를 사용해 토큰 없는 요청을 거부합니다.
  • 접근 제어: JWT claims를 활용해 일반 사용자는 읽기만, 관리자는 모든 작업을 허용하도록 설정할 수 있습니다.

 

Comments