본문 바로가기

API 보안과 SSO를 동시에: Kong 기반 엔터프라이즈 인증 아키텍처 설계 전략

728x90

API Gateway + 인증 게이트 구조

기본 구조는 이렇게 됩니다.

[Client / Browser]
        │  (HTTP, HTTPS)
        ▼
      [Kong Gateway]  ← (Auth Plugin / Custom Plugin / Session Plugin)
        │
        ├─ /auth      → Auth Service (로그인/로그아웃, 세션 생성)
        ├─ /app1      → App1 Service
        ├─ /app2      → App2 Service
        └─ /app3      → App3 Service

여기서 중요한 포인트

  • Kong이 모든 서비스 앞에 서 있는 “인증 게이트” 역할
  • 도메인/서브도메인 동일 → 쿠키 기반 SSO 가능
  • 세션 정보는 Redis 등 공용 저장소에 저장 → 모든 요청에서 공통 검증
  • 백엔드 서비스는 “인증 완료된 사용자 정보만 헤더로 전달받고 사용”
    → 각 서비스는 “인증 로직 최소화” + “권한(Authorization)에만 집중”

두 가지 큰 인증 패턴

Kong으로 구현하는 인증은 크게 두 축으로 보면 이해가 쉽습니다.

  1. API 인증 패턴 – 서비스 간 호출, 외부 파트너 API, 머신 to 머신에 적합
    • Basic Auth
    • Key Auth(API Key)
    • JWT
    • OAuth2 / OIDC (토큰 기반)
  2. 웹 SSO 패턴 – 사용자가 브라우저로 로그인하고 여러 웹 서비스 이용
    • 세션 + 쿠키 + Redis
    • Kong Session Plugin 또는 Custom Plugin / Nginx+Lua

실무에서는 보통 이렇게 조합합니다.

  • 내부/외부 시스템 API → Key-Auth 또는 JWT
  • 내부 관리자·업무 포털 → SSO (세션+쿠키)
  • 외부 IdP(Azure AD, Keycloak 등)와 연계 → OIDC + 세션

기본 docker-compose 구성 요소

  • kong-database (PostgreSQL)
    → Kong 설정, 서비스/라우트/플러그인 메타데이터 저장
  • kong
    → 게이트웨이 본체. 플러그인 실행 위치
  • redis
    → 세션 정보(로그인 사용자 정보, TTL 등) 저장소
  • auth-service
    → 로그인/로그아웃 처리, 세션 생성·삭제, /auth/login, /auth/logout, /auth/verify
  • app1, app2, app3
    → 실제 업무 서비스들

보안 관점 체크포인트

  • Redis에 직접 접근 가능한 네트워크 범위 제한 (Kong / auth-service 만 접근)
  • Postgres, Redis 모두 인증/암호 설정 필수
  • Kong Admin API(8001)는 내부망 전용 또는 VPN 뒤에 두기 (절대 외부 노출 금지)

Kong 기반 API 인증 패턴 정리

1. Basic Auth

  • 헤더: Authorization: Basic base64(username:password)
  • Kong 플러그인: basic-auth

사용 예시

# 서비스에 Basic Auth 플러그인 적용
curl -X POST http://localhost:8001/services/app1-service/plugins \
  --data "name=basic-auth" \
  --data "config.hide_credentials=true"

# Consumer/계정 생성
curl -X POST http://localhost:8001/consumers \
  --data "username=admin"

# 비밀번호 등록
curl -X POST http://localhost:8001/consumers/admin/basic-auth \
  --data "username=admin" \
  --data "password=secure-password"

보안 관점 조언

  • TLS(HTTPS) 필수. 아니면 비밀번호 평문 노출.
  • 장기적으로는 API Key / JWT / OIDC로 전환을 권장.

2. Key Auth (API Key)

  • 헤더: apikey: <key> 또는 X-API-Key: <key>
  • 플러그인: key-auth

서비스 적용

curl -X POST http://localhost:8001/services/app1-service/plugins \
  --data "name=key-auth" \
  --data "config.key_names[]=apikey" \
  --data "config.hide_credentials=true"

Consumer/Key 발급

curl -X POST http://localhost:8001/consumers \
  --data "username=api-user"

curl -X POST http://localhost:8001/consumers/api-user/key-auth \
  --data "key=my-api-key-12345"

보안 관점

  • Key는 1인 1키 또는 시스템 별 키로 발급 후, 유출시 폐기 가능하게 운영
  • 키 사용 로그를 Kong/ES/Wazuh 등으로 수집 → 사용자·시스템별 호출 추적

3. JWT Authentication

  • 토큰: Authorization: Bearer <JWT>
  • 플러그인: jwt

Kong 측

curl -X POST http://localhost:8001/services/app1-service/plugins \
  --data "name=jwt"

Consumer에 JWT 자격 생성

curl -X POST http://localhost:8001/consumers/jwt-user/jwt \
  --data "algorithm=HS256" \
  --data "secret=my-secret-key"
# 응답에서 key (iss), secret 획득

클라이언트 토큰 발급 (Python 예시)

import jwt, time

payload = {
    'iss': 'your-key-from-kong',
    'exp': int(time.time()) + 3600
}

token = jwt.encode(payload, 'my-secret-key', algorithm='HS256')
print(token)

보안 관점

  • exp 필수. 짧은 TTL + Refresh 토큰 구조 고려
  • 비밀키(secret)는 Vault/KMS에 보관, 코드 저장소에 넣지 않기
  • Claim에 역할, 권한 최소한만 포함 (민감정보 X)

4. OAuth2 / OpenID Connect (OIDC)

  • 외부 IdP(Keycloak, Okta, Azure AD 등)와 연동 시 사용
  • Kong 플러그인: oauth2 또는 openid-connect (엔터프라이즈/커뮤니티)

Keycloak 예시 플로우

  1. 사용자가 /app1 접근
  2. 인증되지 않으면 → IdP 로그인 페이지로 리다이렉트
  3. 로그인 성공 → IdP가 Authorization Code + Token 발급
  4. Kong/백엔드에서 토큰 검증 후 세션/쿠키 생성

OIDC 보안 포인트

  • Redirect URI를 정확히 제한 (Open Redirect 방지)
  • state 파라미터 사용으로 CSRF 방지
  • IdP와의 통신은 https + 공개 키 기반 서명 검증

웹 SSO (세션+쿠키) 구조 상세

이제 가장 중요한 “같은 도메인에서 여러 서비스 SSO” 부분을 정리해보겠습니다.

300x250

1. 핵심 아이디어

  1. 하나의 로그인 서비스(auth-service) 에서 로그인 처리
  2. 로그인 성공 시
    • 세션 ID 생성 (session:<username>:<timestamp>)
    • Redis에 세션 객체 저장 (username, role, name, createdAt, TTL 등)
    • 브라우저에 auth_session 쿠키 설정 (도메인 전체에 유효)
  3. 모든 서비스 요청은 Kong/Nginx에서 쿠키 → Redis → 세션 검증
  4. 검증 후 X-User-Id, X-User-Role, X-User-Name 헤더로 각 서비스에 전달

2. Auth Service 역할 (Node.js 예시 기반 정리)

Auth Service 주요 엔드포인트

  • GET /auth/login
    • 로그인 페이지 렌더링 (HTML 폼)
  • POST /auth/login
    • 아이디/비밀번호 검증
    • JWT/세션 ID 발급
    • Redis에 세션 저장
    • auth_session 쿠키 설정
  • POST /auth/logout
    • Redis에서 세션 삭제
    • 쿠키 삭제
  • GET /auth/verify
    • Kong/게이트웨이가 호출하는 세션 검증용 API
  • GET /auth/me
    • 현재 로그인 사용자 정보 조회

보안 관점

  • 로그인 시도 실패 횟수 제한 (브루트포스 방지)
  • 비밀번호는 반드시 bcrypt 등으로 해시 저장
  • 관리자 계정은 별도의 강화된 정책 (IP 제한, MFA 등)

3. Kong에서 세션 검증하는 두 가지 방법

① Session 플러그인 + 별도 검증 로직 요청

  • Kong Session 플러그인으로 쿠키 관리 + Redis 저장소 연계
  • /auth/verify 엔드포인트와 연계 가능
  • 상대적으로 구현 난이도 낮음, 플러그인 설정으로 처리

② Custom Plugin (Lua) 직접 구현

사용하신 예시처럼, Lua로 Redis에 직접 연결해서 세션 검증

  • 인증 제외 경로
    • /auth/*, /health, /static
  • 나머지 요청
    1. auth_session 쿠키 파싱
    2. Redis에서 세션 조회
    3. 없으면 /auth/login?redirect=<원래 URL> 로 302 리다이렉트
    4. 있으면 사용자 정보를 헤더에 추가 후 백엔드 호출

보안 체크포인트

  • redirect URL 화이트리스트 또는 도메인 체크 (Open Redirect 방지)
  • Redis 오류 시 fallback 정책
    • FA(“모두 차단”)가 기본. (Redis 장애 → 인증 불가 → 서비스 영향 vs 보안)
    • 장애 시 읽기 전용 모드 또는 점검 페이지 안내 고려

4. Nginx + Lua로 직접 구현하는 경우

Kong 없이 Nginx만 쓴다면

  • access_by_lua_file 에서 세션 검증 스크립트 실행
  • location 블록에서 $auth_passed 여부에 따라 /auth/login으로 리다이렉트
  • 백엔드에는 X-User-* 헤더로 사용자 정보 전달

이 방식은 Kong 없이도 작동하지만

  • Kong의 장점(플러그인, 관리 UI, 통계, Rate Limiting, Key-Auth 등)을 활용 못함
  • 이미 Kong을 도입한다면 Custom Plugin 또는 Kong+Nginx 조합이 더 전략적

백엔드 서비스에서의 처리 방식

각 서비스는 다음 원칙만 지키면 됩니다.

  1. 인증은 Kong/게이트웨이가 책임진다.
  2. 서비스는 헤더로 들어온 사용자 정보만 신뢰하고 사용.
  3. 서비스에서 직접 쿠키/세션을 다루지 않는다. (가능하면)

예: Express.js에서 사용자 정보 활용

app.get('/api/data', (req, res) => {
  const userId = req.headers['x-user-id'];
  const userRole = req.headers['x-user-role'];
  const userName = req.headers['x-user-name'];

  // 권한 체크
  if (userRole !== 'admin') {
    return res.status(403).json({ error: 'Forbidden' });
  }

  res.json({ message: `Hello ${userName}(${userId})` });
});

보안 관점

  • 절대 클라이언트에서 임의 헤더로 X-User-* 넣는 상황을 허용하면 안 됨
    • Kong ↔ Backend 사이 통신은 내부망/전용 네트워크로 고정
    • 외부에서 직접 백엔드 접속 불가하게 방화벽·보안그룹 설계

보안 관점 체크리스트

도입 시 내부 개발·운영팀에게 줄 수 있는 점검/가이드 포인트를 정리하면

  1. Gateway 경로 통제
    • 모든 서비스 진입점은 Kong만 사용
    • 백엔드 서비스 포트는 외부에서 직접 접근 불가 (FW, SG, NACL 등)
  2. 쿠키/세션 관리
    • auth_session 쿠키 HttpOnly, Secure(HTTPS 시), SameSite=Lax/Strict 적용
    • 세션 TTL 명확히 정의(예: 1시간), Idle Timeout 정책 설정
    • 로그아웃 시 세션 즉시 폐기 + 쿠키 삭제
  3. Redis / DB 보안
    • Redis는 내부 네트워크에서만 접근 가능
    • 필요시 Redis AUTH 사용 및 TLS 적용
    • 세션 데이터에 민감정보(비밀번호, 주민번호 등) 저장 금지
  4. 인증·권한 분리
    • 인증(AuthN)은 Gateway / Auth Service에서 처리
    • 권한(AuthZ)은 각 서비스에서 헤더 기반으로 처리 (Role, Scope 등)
  5. 로그·모니터링
    • Kong Proxy/Plugin 로그를 중앙 로그 시스템(Elastic, Wazuh, Chronicle 등)으로 수집
    • 다음 항목을 최소 수집
      • Consumer/사용자 ID
      • 요청 URL/메서드
      • 응답 코드
      • Fail Reason (401/403 사유)
    • 이상 징후 탐지
      • 특정 계정의 과도한 로그인 실패
      • 비정상 API 호출 패턴 (Rate limiting 우회 시도 등)
  6. 관리 인터페이스 보호
    • Kong Admin API, Konga/Kong Manager는 내부망 + VPN + IP 제한
    • 별도 관리자 계정과 MFA 적용
  7. 정책 문서화
    • “인증/SSO 표준 아키텍처” 문서
    • “서비스 신규 오픈 시 Kong 등록 절차 + 인증 패턴 선택 가이드”
    • “Key/JWT 발급·회수 절차”, “권한(Role) 설계 기준”

단계별 도입 로드맵 (실행 순서 요약)

마지막으로, 실제 도입을 한다고 가정하고 “어떻게 진행할지”를 한 번에 볼 수 있게 정리해보면

  1. 기초 인프라 준비
    • Kong + Postgres + Redis + Auth Service + 샘플 App1, App2, App3 docker-compose로 구동
  2. Kong 서비스/라우트/플러그인 정의
    • /auth, /app1, /app2, /app3 서비스와 라우트 추가
    • 첫 단계에서는 Key-Auth / Basic-Auth로 API 인증 흐름부터 익히기
  3. Auth Service 완성
    • 로그인/로그아웃, 세션 생성, Redis 저장, /auth/verify 구현
  4. 세션 기반 SSO 적용
    • Kong Session 플러그인 또는 Custom Plugin으로 세션 검증 로직 적용
    • 브라우저 기준 /auth/login → /app1 /app2 /app3 SSO 동작 확인
  5. OIDC/외부 IdP 연동 (선택)
    • Keycloak 또는 사내 SSO(IdP)와 OIDC 연동
    • 외부 계정체계 ↔ Kong ↔ 내부 서비스 SSO 완성
  6. 운영·보안 가드레일 정비
    • 로그 수집 → SIEM(Wazuh, Elastic, Chronicle 등) 연동
    • Rate Limiting, IP Restriction, CORS 등 공통 보안 플러그인 설정
    • 운영가이드/보안정책 문서화
728x90
그리드형(광고전용)

댓글