API 호출을 인증하는 여러 방법이 있지만, OAuth 2.0 인증 메커니즘이 주로 사용됩니다. 여기서 OAuth 2.0 액세스 토큰은 클라이언트로부터 API 서버로 전달되는 인증 자격 증명으로, 대개 HTTP 헤더로 운반됩니다.
Keycloak은 OAuth 2.0의 확장인 OIDC를 지원하며, 클라이언트를 인증할 때 IdP(신원 제공자)로 작동합니다.
IdP와 액세스 토큰의 유효성을 확인하는 표준 방법을 토큰 인트로스펙션(token introspection)이라고 합니다. Nginx는 OAuth 2.0 의존 파티로서, IdP에 액세스 토큰을 보내 유효성을 검사(토큰 인트로스펙션)하고, 검증을 통과한 요청만을 프록시합니다.
그렇다면 왜 Nginx에서 토큰 유효성 검사를 수행할까요? 각 백엔드 서비스나 애플리케이션에서 검증을 수행하면, 많은 중복 코드와 불필요한 처리가 발생합니다. 다양한 오류 조건과 예외 사항을 고려해야 하며, 이를 각 백엔드 서비스에서 수행하는 것은 구현상의 일관성이 떨어지고 결과적으로 사용자 경험이 예측 불가능해지는 원인이 됩니다.
이러한 코드 중복과 결과적인 문제를 피하기 위해, 우리는 Nginx를 사용하여 백엔드 서비스를 대신해 액세스 토큰의 유효성을 검사할 수 있습니다. 이 접근 방식을 통해, 우리는 하나의 중앙 집중식 위치에서 보안 검증을 수행할 수 있으며, 각각의 백엔드 서비스나 애플리케이션에서 이를 반복 구현할 필요가 없게 됩니다. 이는 개발의 복잡성을 줄이고, 보안 구현의 일관성을 유지하는 데 도움이 됩니다.
Nginx 와 Keycloak을 사용하여 프록시된 애플리케이션에 대한 SSO(Single Sign-On) 구성 방법은 OpenID Connect(OIDC) 인증 메커니즘을 기반으로 합니다. OIDC는 OAuth 2.0 위에 위치하는 얇은 계층으로, Keycloak을 신원 제공자(IdP)로, OpenResty를 의존 엔티티로 사용합니다.
기본 사항
- OAuth 2.0: 클라이언트와 API 서버 간에 인증 정보를 전달하는 데 주로 사용되며, HTTP 헤더를 통해 전달됩니다.
- Keycloak: OIDC를 지원하며 클라이언트를 인증하는 데 사용되는 IdP입니다.
- Nginx: OAuth 2.0 의존 파티로서, IdP에 액세스 토큰을 보내 유효성을 검사합니다.
Nginx 와 Keycloak 통합
- Dockerfile 작성: OpenResty를 사용하기 위한 Nginx 이미지를 빌드합니다.
FROM openresty/openresty:alpine-fat RUN mkdir /var/log/nginx RUN apk add --no-cache openssl-dev git gcc RUN luarocks install lua-resty-openidc ENTRYPOINT ["/usr/local/openresty/nginx/sbin/nginx", "-g", "daemon off;"] EXPOSE 80
- nginx.conf 설정: 두 개의 백엔드 애플리케이션 보호 구성입니다.
upstream app_a { server app_1:80; } upstream app_b { server app_2:80; } server { listen 3002; resolver 127.0.0.11 valid=1s ipv6=off; access_by_lua ' local opts = { -- 여기에 OIDC 설정을 추가합니다. } local res, err = require("resty.openidc").authenticate(opts) if err then ngx.status = 403 ngx.say(err) ngx.exit(ngx.HTTP_FORBIDDEN) end '; location / { proxy_pass http://app_a; } } server { listen 4090; resolver 127.0.0.11 valid=1s ipv6=off; access_by_lua ' local opts = { -- 여기에 OIDC 설정을 추가합니다. } local res, err = require("resty.openidc").authenticate(opts) if err then ngx.status = 403 ngx.say(err) ngx.exit(ngx.HTTP_FORBIDDEN) end '; location / { proxy_pass http://app_b; } }
Keycloak 설정
- 새로운 Realm 생성: Keycloak 관리 포털에서 'myrealm'과 같은 새로운 realm을 생성합니다.
- 클라이언트 추가: 필요에 따라 새 클라이언트를 추가하고, 유효한 리디렉션 URI를 설정합니다.
- 클라이언트 비밀 추가: Credentials 탭에서 생성된 비밀키를 Nginx 설정 파일에 추가합니다.
사용자 추가
- 사용자 세부 정보 추가: 애플리케이션 접근 시 인증을 위해 사용자를 추가합니다.
- 사용자 비밀번호 설정: 사용자에게 비밀번호를 설정합니다.
Docker-compose 사용
- 서비스 정의: Postgres, Keycloak, Nginx 및 데모 애플리케이션(app_1, app_2) 컨테이너를 포함하는
docker-compose.yml
파일을 작성합니다.version: "3" services: postgres: image: postgres environment: POSTGRES_DB: keycloak POSTGRES_USER: keycloak POSTGRES_PASSWORD: password keycloak: image: jboss/keycloak environment: DB_VENDOR: POSTGRES KEYCLOAK_USER: admin KEYCLOAK_PASSWORD: password app_1: image: nginx app_2: image: nginx nginx: build: .nginx/ ports: - 3002:3002 - 4090:4090
- 동작 확인: 모든 것이 정상적으로 구동되면, 포트 3002와 4090에 액세스하려는 모든 시도는 Keycloak 로그인 페이지로 리디렉션되며, 로그인 성공 후 요청한 리소스에 접근할 수 있습니다.
이 과정을 통해 NGINX와 Keycloak을 사용하여 SSO를 구성하고, 프록시된 애플리케이션에 대한 보안 접근을 관리할 수 있습니다.
댓글