티스토리 뷰
작성일: 2026년 1월 2일
카테고리: Kubernetes, API Gateway, Security
키워드: Envoy Gateway, SecurityPolicy, JWT, OIDC, ExtAuth, CORS, API Key
시리즈: Envoy Gateway 완벽 가이드 (4/6)
요약
Envoy Gateway의 SecurityPolicy는 API 보안의 핵심이다. JWT 검증, OIDC 인증, 외부 인증 서비스, API Key, CORS 등 다양한 인증/인가 메커니즘을 선언적으로 설정할 수 있다. 이 글에서는 각 인증 방식의 동작 원리와 실전 설정 예제를 다룬다.
SecurityPolicy 인증 흐름
SecurityPolicy는 요청이 백엔드에 도달하기 전에 인증 검증을 수행한다.
graph LR
Client[클라이언트]
SP[SecurityPolicy]
HR[HTTPRoute]
Backend[백엔드]
Client -->|1. 요청| SP
SP -->|2a. 인증 성공| HR
SP -->|2b. 인증 실패 401/403| Client
HR -->|3. 라우팅| Backend
style SP stroke:#dc2626,stroke-width:3px
style HR stroke:#16a34a,stroke-width:2px
JWT 인증
JWT란?
JWT(JSON Web Token)는 당사자 간 정보를 안전하게 전송하기 위한 개방형 표준(RFC 7519)이다. 토큰 자체에 사용자 정보가 포함되어 있어 별도 세션 저장소가 필요 없다.
JWKS(JSON Web Key Set)
JWT를 검증하려면 서명에 사용된 공개 키가 필요하다. JWKS는 이 키들을 JSON 형식으로 제공하는 엔드포인트다.
graph LR
Client[클라이언트]
EG[Envoy Gateway]
JWKS[JWKS 엔드포인트]
Backend[백엔드]
Client -->|1. JWT 포함 요청| EG
EG -->|2. 공개 키 조회| JWKS
JWKS -->|3. 키 반환| EG
EG -->|4. JWT 검증| EG
EG -->|5. 검증 성공| Backend
style EG stroke:#2563eb,stroke-width:3px
기본 설정: Remote JWKS
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-auth
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: api-route
jwt:
providers:
- name: auth0
# JWKS 엔드포인트
remoteJWKS:
uri: https://my-tenant.auth0.com/.well-known/jwks.json
고급 설정: Claim을 헤더로 전달
JWT의 claim 값을 백엔드로 전달할 수 있다.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-with-claims
spec:
targetRef:
kind: HTTPRoute
name: api-route
jwt:
providers:
- name: my-provider
remoteJWKS:
uri: https://auth.example.com/.well-known/jwks.json
# Claim을 헤더로 변환
claimToHeaders:
- claim: sub
header: X-User-ID
- claim: email
header: X-User-Email
- claim: "realm_access.roles"
header: X-User-Roles
백엔드 서비스는 이 헤더를 읽어 사용자 정보를 활용할 수 있다:
X-User-ID: user123
X-User-Email: user@example.com
X-User-Roles: ["admin", "user"]Local JWKS (ConfigMap)
JWKS를 외부에서 가져오지 않고 직접 설정할 수 있다.
apiVersion: v1
kind: ConfigMap
metadata:
name: jwt-local-jwks
data:
jwks: |
{
"keys": [{
"kty": "RSA",
"use": "sig",
"alg": "RS256",
"kid": "my-key-id",
"n": "xOHb-i1WDfe...",
"e": "AQAB"
}]
}
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-local
spec:
targetRef:
kind: HTTPRoute
name: api-route
jwt:
providers:
- name: local-provider
localJWKS:
type: ValueRef
valueRef:
group: ""
kind: ConfigMap
name: jwt-local-jwks
자체 서명 인증서 JWKS 연결
내부 인증 서버가 자체 서명 인증서를 사용하는 경우:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-self-signed
spec:
targetRef:
kind: HTTPRoute
name: api-route
jwt:
providers:
- name: internal-auth
remoteJWKS:
uri: https://auth.internal.com/.well-known/jwks.json
backendRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: auth-backend
port: 443
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
name: auth-backend
spec:
endpoints:
- fqdn:
hostname: auth.internal.com
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: auth-tls
spec:
targetRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: auth-backend
validation:
caCertificateRefs:
- name: auth-ca-cert
group: ""
kind: ConfigMap
hostname: auth.internal.com
External Authorization (ExtAuth)
ExtAuth란?
ExtAuth는 인증/인가 로직을 외부 서비스에 위임하는 패턴이다. 복잡한 비즈니스 로직이나 기존 인증 시스템과의 통합에 적합하다.
graph LR
Client[클라이언트]
EG[Envoy Gateway]
ExtAuth[ExtAuth 서비스]
Backend[백엔드]
Client -->|1. 요청| EG
EG -->|2. 인증 확인| ExtAuth
ExtAuth -->|3a. 200 OK + 헤더| EG
ExtAuth -->|3b. 403 Forbidden| EG
EG -->|4. 인증 성공 시| Backend
style ExtAuth stroke:#ea580c,stroke-width:3px
HTTP ExtAuth
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: http-ext-auth
spec:
targetRef:
kind: HTTPRoute
name: api-route
extAuth:
http:
backendRefs:
- name: auth-service
port: 9001
# ExtAuth 서비스로 전달할 헤더
headersToExtAuth:
- Authorization
- X-Tenant-ID
# 인증 성공 시 백엔드로 전달할 헤더
headersToBackend:
- X-User-ID
- X-User-Roles
gRPC ExtAuth
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: grpc-ext-auth
spec:
targetRef:
kind: HTTPRoute
name: api-route
extAuth:
grpc:
backendRefs:
- name: grpc-auth-service
port: 9002
ExtAuth 서비스 구현 예시 (Go)
// HTTP ExtAuth 서비스 예시
func authHandler(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
// 토큰 검증 로직
userID, roles, err := validateToken(token)
if err != nil {
w.WriteHeader(http.StatusForbidden)
return
}
// 인증 성공 - 사용자 정보를 헤더로 반환
w.Header().Set("X-User-ID", userID)
w.Header().Set("X-User-Roles", strings.Join(roles, ","))
w.WriteHeader(http.StatusOK)
}
OIDC 인증
OIDC란?
OIDC(OpenID Connect)는 OAuth 2.0 기반의 인증 표준이다. 사용자가 Google, Auth0, Keycloak 등의 Provider로 로그인하면, Gateway가 자동으로 인증 플로우를 처리한다.
graph TB
User[사용자]
EG[Envoy Gateway]
Provider[OIDC Provider]
Backend[백엔드]
User -->|1. 보호된 리소스 접근| EG
EG -->|2. 로그인 페이지로 리다이렉트| User
User -->|3. 로그인| Provider
Provider -->|4. 인증 코드| EG
EG -->|5. 토큰 교환| Provider
Provider -->|6. ID Token| EG
EG -->|7. 세션 쿠키 설정| User
User -->|8. 리소스 접근| EG
EG -->|9. 요청 전달| Backend
style EG stroke:#2563eb,stroke-width:3px
style Provider stroke:#ea580c,stroke-width:2px
기본 설정
apiVersion: v1
kind: Secret
metadata:
name: oidc-client-secret
type: Opaque
stringData:
client-secret: your-client-secret-here
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: oidc-auth
spec:
targetRef:
kind: HTTPRoute
name: web-app
oidc:
provider:
issuer: "https://accounts.google.com"
clientID: "your-client-id"
clientSecret:
name: "oidc-client-secret"
# 리다이렉트 URL은 HTTPRoute와 일치해야 함
redirectURL: "https://app.example.com/oauth2/callback"
logoutPath: "/logout"
다중 도메인 쿠키 공유
여러 서브도메인에서 OIDC 세션을 공유하려면 cookieDomain을 설정한다.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: oidc-multi-domain
spec:
targetRef:
kind: Gateway
name: my-gateway
oidc:
provider:
issuer: "https://accounts.google.com"
clientID: "your-client-id"
clientSecret:
name: "oidc-client-secret"
redirectURL: "https://www.example.com/oauth2/callback"
logoutPath: "/logout"
# 서브도메인 간 쿠키 공유
cookieDomain: "example.com"
Keycloak 연동 (자체 서명 인증서)
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: keycloak-oidc
spec:
targetRef:
kind: HTTPRoute
name: web-app
oidc:
provider:
issuer: "https://keycloak.internal.com/realms/master"
authorizationEndpoint: "https://keycloak.internal.com/realms/master/protocol/openid-connect/auth"
tokenEndpoint: "https://keycloak.internal.com/realms/master/protocol/openid-connect/token"
backendRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: keycloak-backend
port: 443
clientID: "my-app"
clientSecret:
name: "keycloak-secret"
redirectURL: "https://app.example.com/oauth2/callback"
logoutPath: "/logout"
API Key 인증
API Key란?
API Key는 클라이언트를 식별하는 간단한 문자열이다. 서버 간 통신이나 공개 API 접근 제어에 주로 사용된다.
설정
# API Key 저장용 Secret
apiVersion: v1
kind: Secret
metadata:
name: api-keys
type: Opaque
stringData:
# 클라이언트ID: API Key
client-a: "sk_live_abc123"
client-b: "sk_live_xyz789"
mobile-app: "sk_live_mobile_456"
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: apikey-auth
spec:
targetRef:
kind: HTTPRoute
name: api-route
apiKeyAuth:
credentialRefs:
- group: ""
kind: Secret
name: api-keys
extractFrom:
# 헤더에서 추출
- headers:
- X-API-Key
- Authorization
# 쿼리 파라미터에서 추출
- params:
- api_key
테스트
# 헤더로 API Key 전달
curl -H "X-API-Key: sk_live_abc123" https://api.example.com/v1/users
# 쿼리 파라미터로 전달
curl "https://api.example.com/v1/users?api_key=sk_live_abc123"
CORS 설정
CORS란?
CORS(Cross-Origin Resource Sharing)는 브라우저가 다른 도메인의 리소스에 접근할 수 있도록 허용하는 메커니즘이다. 프론트엔드(app.example.com)가 백엔드 API(api.example.com)를 호출할 때 필요하다.
SecurityPolicy로 설정
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: cors-policy
spec:
targetRef:
kind: HTTPRoute
name: api-route
cors:
# 허용할 Origin
allowOrigins:
- "https://app.example.com"
- "https://*.example.com" # 와일드카드
# 허용할 HTTP 메서드
allowMethods:
- GET
- POST
- PUT
- DELETE
- OPTIONS
# 허용할 요청 헤더
allowHeaders:
- Authorization
- Content-Type
- X-Request-ID
# 노출할 응답 헤더
exposeHeaders:
- X-Rate-Limit-Remaining
- X-Request-ID
# Preflight 캐시 시간 (초)
maxAge: 86400
# 자격 증명 허용
allowCredentials: true
HTTPRoute 필터로 설정
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
spec:
parentRefs:
- name: eg
rules:
- backendRefs:
- name: backend
port: 8080
filters:
- type: CORS
cors:
allowOrigins:
- "https://app.example.com"
allowMethods:
- GET
- POST
allowHeaders:
- Authorization
imprun 인증 모드 매핑
imprun apigateway의 인증 설정이 SecurityPolicy로 어떻게 변환되는지 정리한다.
| imprun auth_mode | SecurityPolicy 필드 | 비고 |
|---|---|---|
jwt |
.spec.jwt |
JWKS URL 필요 |
apikey |
.spec.apiKeyAuth 또는 .spec.extAuth |
단순 검증은 apiKeyAuth, 복잡한 로직은 ExtAuth |
oidc |
.spec.oidc |
Provider 연동 필요 |
basic |
.spec.basicAuth |
htpasswd Secret 참조 |
none |
정책 미적용 | HTTPRoute에 SecurityPolicy 없음 |
변환 예시
imprun 설정:
{
"route": "/api/v1/*",
"auth_mode": "jwt",
"auth_config": {
"jwks_uri": "https://auth.example.com/.well-known/jwks.json",
"claim_to_headers": {
"sub": "X-User-ID",
"tenant_id": "X-Tenant-ID"
}
}
}
생성되는 SecurityPolicy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: route-api-v1-auth
namespace: tenant-abc
spec:
targetRef:
kind: HTTPRoute
name: api-v1
jwt:
providers:
- name: default
remoteJWKS:
uri: https://auth.example.com/.well-known/jwks.json
claimToHeaders:
- claim: sub
header: X-User-ID
- claim: tenant_id
header: X-Tenant-ID
디버깅 가이드
인증 실패 시 확인 사항
| 증상 | 원인 | 해결책 |
|---|---|---|
401 Jwt is missing |
JWT 누락 | Authorization 헤더 확인 |
401 Jwt verification fails |
JWT 서명 불일치 | JWKS URI, 토큰 발급자 확인 |
403 RBAC: access denied |
인가 규칙 불일치 | Authorization 규칙 확인 |
503 Service Unavailable |
ExtAuth 서비스 다운 | ExtAuth 서비스 상태 확인 |
SecurityPolicy 상태 확인
kubectl get securitypolicy my-policy -o yaml
# 예상 출력
status:
conditions:
- type: Accepted
status: "True"
- type: Programmed
status: "True"
다음 글 미리보기
Envoy Gateway 트래픽 관리에서는 Rate Limiting, Circuit Breaker, Load Balancing을 다룬다.
참고 자료
공식 문서
관련 블로그
시리즈 네비게이션
| 이전 글 | 다음 글 |
|---|---|
| 확장 API: Policy Attachment 모델 | 트래픽 관리: Rate Limiting, Circuit Breaker |
Envoy Gateway 완벽 가이드 시리즈
- Envoy Gateway 개요
- Gateway API 핵심 리소스
- 확장 API
- 보안: 인증/인가 완벽 가이드 ← 현재 글
- 트래픽 관리
- 확장성
'실제 경험과 인사이트를 AI와 함께 정리한 글' 카테고리의 다른 글
| Envoy Gateway 확장성: External Processing, WASM, Lua (1) | 2026.01.02 |
|---|---|
| Envoy Gateway 트래픽 관리: Rate Limiting, Circuit Breaker, Load Balancing (1) | 2026.01.02 |
| Gateway API 핵심 리소스 가이드: GatewayClass, Gateway, HTTPRoute (0) | 2026.01.02 |
| Envoy Gateway 개요: Kubernetes 네이티브 API Gateway의 새로운 표준 (0) | 2026.01.02 |
| Claude Code 2025.12월 사용 리포트 (0) | 2026.01.02 |
- Total
- Today
- Yesterday
- Go
- authentication
- AI
- AGENTS.md
- imprun.dev
- Tailwind CSS
- feature-sliced design
- security
- troubleshooting
- GPT-5.1
- claude code
- api gateway
- ai coding
- Claude Opus 4.5
- authorization
- EnvironmentAgnostic
- NestJS
- Kubernetes
- Next.js
- react
- Development Tools
- Gemini 3.0
- frontend
- architecture
- backend
- zustand
- AI agent
- CLAUDE.md
- Claude
- Developer Tools
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
