NGINX Ingress Controller API 인가 – Keycloak 연동 구현
이 포스트는 NGINX Ingress Controller, Keycloak 연동을 통한 API 인가 구현 방법을 다룹니다. NGINX Ingress Controller와 Keycloak의 OIDC 인증 과정에서 ID 토큰과 함께 발급되는 Access 토큰을 백엔드 애플리케이션으로 전달하고, 해당 토큰의 클레임값을 통해 API 인가를 구현합니다. NGINX Ingress Controller의 OIDC 인증 기능은 NGINX Ingress Controller의 상업 구독 버전인 NGINX Plus Ingress Controller 전용 기능입니다.
NGINX Ingress Controller의 Policy 설정을 통해 인증 과정에서 발급되는 Access 토큰을 백엔드 애플리케이션으로 전달하도록 하는 방법을 알아보고, Access 토큰의 클레임값에 따라 접근 권한이 제한된 간단한 애플리케이션 구성을 통해 API 인가를 구현해 보겠습니다.
이 포스트는 이전 포스트인 NGINX Ingress Controller Keycloak 활용 API 인증 구현 가이드의 구성에 이어서 진행됩니다.
목차
1. NGINX Ingress Controller API 인가 – Access 토큰
2. 버전 정보
3. NGINX Ingress Controller, 백엔드 애플리케이션 구성
4. Keycloak 구성
5. NGINX Ingress Controller API 인가 확인
6. 결론
1. NGINX Ingress Controller API 인가 – Access 토큰

지난 포스트에서는 NGINX Ingress Controller와 Keycloak을 연동한 OIDC 인증 흐름에서 사용자 인증에 사용되는 ID 토큰만을 다뤘습니다. 그러나 실제로는 인증 과정에서 ID 토큰과 함께 인가에 사용되는 Access 토큰도 NGINX Ingress Controller로 전달됩니다(8번 과정).
NGINX Ingress Controller는 ID 토큰을 검증한 후, keyval store에 ID 토큰과 Access 토큰을 모두 저장합니다(9번 과정). 저장된 Access 토큰은 NGINX Ingress Controller의 Policy 설정을 통해 백엔드 애플리케이션으로 전달됩니다(13번 과정).
Access 토큰은 Keycloak에서 사용자의 group 및 role 등의 정보를 클레임에 담아 전달하며, 백엔드 애플리케이션은 이 정보를 통해 사용자의 권한을 확인하고, 이를 기반으로 인가 처리를 수행합니다.
2. 버전 정보
- Kubernetes: v1.30.3
- NGINX Plus Ingress Controller: 4.0.0
- Keycloak: 26.1.0
3. NGINX Ingress Controller, 백엔드 애플리케이션 구성
기존에 구성한 Policy 리소스에서 Access 토큰을 백엔드 애플리케이션으로 전달하기 위한 설정을 추가합니다.
oidc-policy.yaml
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: oidc-policy
namespace: app
spec:
oidc:
clientID: nginx-ingress
clientSecret: oidc-secret
authEndpoint: https://devopssong2.nginxstore.kr/realms/nginx/protocol/openid-connect/auth
tokenEndpoint: https://devopssong2.nginxstore.kr/realms/nginx/protocol/openid-connect/token
jwksURI: https://devopssong2.nginxstore.kr/realms/nginx/protocol/openid-connect/certs
endSessionEndpoint: https://devopssong2.nginxstore.kr/realms/nginx/protocol/openid-connect/logout
accessTokenEnable: true
Policy 리소스에 해당 설정을 추가하게 되면, NGINX Ingress Controller가 백엔드 애플리케이션으로 요청을 프록시 할 때, Authorization 헤더에 “Bearer $access_token” 값을 담아 전달하게 됩니다.
이전 포스트에서 백엔드 애플리케이션으로 구성했던 NGINX Pod 대신, Access 토큰의 클레임을 통해 접근 권한을 확인하는 Python 애플리케이션을 배포합니다. 해당 애플리케이션의 특징은 다음과 같습니다.
- /, /admin, /token 3개의 엔드포인트가 구성되어 있습니다.
- / 엔드포인트는 모든 사용자가 접근할 수 있습니다
- /admin 엔드포인트는 admin role을 가지고 있는 사용자만 접근할 수 있습니다
- /token 엔드포인트는 사용자의 Access 토큰값을 출력합니다
- NGINX Ingress Controller로부터 전달받은 Access 토큰을 검증하고, 디코딩하여 클레임값을 확인합니다.
- aud 클레임값이 Keycloak의 클라이언트 ID값과 동일한지 확인합니다.
애플리케이션 빌드에 사용한 코드는 NGINX STORE GitHub에서 확인하실 수 있습니다.
애플리케이션을 Deployment로 배포합니다.
oidc-backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: oidc-backend
spec:
replicas: 1
selector:
matchLabels:
app: oidc-backend
template:
metadata:
labels:
app: oidc-backend
spec:
containers:
- name: oidc-backend
image: yjsitian/public:oidc-backend-2.4
ports:
- containerPort: 5000
env:
- name: KEYCLOAK_PUBLIC_KEY_URL
value: "https://devopssong2.nginxstore.kr/realms/nginx/protocol/openid-connect/certs" # Keycloak 공개키 URL
- name: KEYCLOAK_CLIENT_ID
value: "nginx-ingress" # Keycloak 클라이언트 ID
Access 토큰 검증을 위한 값을 환경 변수로 구성합니다.
Pod 연결을 위한 Service도 배포합니다.
oidc-backend-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: oidc-backend-svc
spec:
selector:
app: oidc-backend
ports:
- protocol: TCP
port: 80
targetPort: 5000
type: ClusterIP
변경된 Service에 맞춰 VirtualServer를 수정합니다.
backend-vs.yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: backend-vs
namespace: app
spec:
host: devopssong.nginxstore.kr
tls:
secret: devopssong-nginxstore
upstreams:
- name: backend
service: oidc-backend-svc
port: 80
routes:
- path: /
policies:
- name: oidc-policy
action:
pass: backend
4. Keycloak 구성
Keycloak에 admin 사용자로 접속합니다. 이전에 생성한 nginx realm에서 진행합니다.

Clients 메뉴에서 이전에 생성한 Client(nginx-ingress)를 선택하여 Roles 메뉴에서 role을 추가합니다.
admin과 user를 구성했습니다.


Client 단위가 아닌 realm 단위의 role을 구성하려면 좌측의 Realm roles 메뉴에서 구성할 수 있습니다.
Realm 생성 시 기본적으로 생성되는 role을 확인할 수 있습니다.

사용자에게 role을 부여하기 위해 Users 메뉴에서 role을 부여할 사용자를 선택해 Assign role 버튼을 클릭합니다.

default-roles-nginx는 realm에 생성된 사용자에게 자동으로 부여되는 role입니다.

Client에 생성한 role 적용을 위해 Filter by clients를 선택하고, user role을 부여합니다.


새로 추가한 user role이 부여되며, Hide inherited roles 체크 박스를 해제하면 default-roles-nginx 하위에 정의된 role도 모두 확인할 수 있습니다. Keycloak 계정 정보를 위한 role이 구성되어 있습니다.
비교를 위해 devopssong 사용자를 생성하고, admin role을 부여했습니다.

adu 클레임값에 client(nginx-ingress)정보를 추가하기 위해 Client scopes 메뉴의 nginx-ingress-dedicated를 선택합니다. aud 클레임은 토큰의 대상자(audience)를 나타내는 클레임입니다.

아래 단계를 따라 Access 토큰의 aud 클레임값에 nginx-ingress를 추가할 수 있습니다.



이름은 임의로 지정하고, Included Client Audience 값을 지정하고, Add to access token을 활성화합니다.
추가로 Scope 메뉴의 Full scope allowed를 비활성화합니다. 해당 값을 비활성화하여 Access 토큰의 대상이 되는 Client(애플리케이션)에 대한 role 정보만 전달하도록 설정할 수 있습니다.

비활성화 시

활성화 시 : nginx-ingress 관련 role뿐만이 아닌, account 관련 role도 전부 포함됩니다.

5. NGINX Ingress Controller API 인가 확인
웹 브라우저를 통해 VirtualServer 리소스에 구성된 도메인으로 접속하여 johndoe 사용자로 로그인하면, 사진과 같이 메시지와 함께 클레임에 담긴 사용자 이름을 출력합니다.

/admin 경로로 접근 시 해당 사용자는 권한이 없어 접근하지 못합니다.

/token 경로 접근 시 Access 토큰의 값을 확인할 수 있습니다.
설정한 aud, role 등 전체 토큰 정보를 확인할 수 있습니다.
로그아웃 후 admin role이 부여된 devopssong 사용자로 로그인합니다.

/admin 경로로 문제없이 접근할 수 있습니다.

/token에서 Access 토큰의 내용을 확인하면 다음과 같습니다.

6. 결론
이번 포스트에서는 NGINX Ingress Controller를 Keycloak과 연동하여, OIDC 인증을 통해 발급되는 Access 토큰으로 API 인가를 구현하는 방법을 알아봤습니다.
Access 토큰 전달을 위해 필요한 NGINX Ingress Controller의 Policy 설정 방법을 알아보고, Access 토큰의 클레임값에서 role을 확인하고 이에 따라 접근 제한이 설정된 간단한 애플리케이션을 구성했습니다. 그리고 Keycloak 설정을 통해 role을 추가하고 사용자에게 할당하는 방법과, Access 토큰의 aud 클레임에 Keycloak의 client 값을 추가하는 방법을 알아봤습니다.
NGINX Ingress Controller와 Keycloak을 연동하여 API 인증 및 인가를 처리하면, 인증 관리의 중앙화, 표준화된 인증 프로토콜 적용, 역할 기반 접근 제어 등 다양한 이점을 누릴 수 있습니다. 이러한 방식은 보안을 강화하고, 관리의 복잡성을 줄이며, 사용자 경험을 향상하는 데 큰 도움이 됩니다.
Keycloak과 연동하여 OIDC 인증을 통해 API 인증/인가를 구현할 수 있는 NGINX Ingress Controller를 체험해 보고 싶으시다면, NGINX STORE를 통해 문의해 무료로 NGINX의 상업 구독을 체험해 보세요.
댓글을 달려면 로그인해야 합니다.