JWT 프로바이더 구성 항목 참조
JWT 프로바이더 구성 항목 참조 (JWT Provider)
JWT 프로바이더 구성 항목에 대한 참조 정보를 제공하는 문서예요. 이 구성 항목은 서비스 메시의 프록시에 JWT 검증을 추가하기 위해 JSON Web Token(JWT)과 JSON Web Key Set(JWKS)을 사용하도록 Consul을 구성해요.
출처: 문서
본문
이 페이지는 JWT 프로바이더 구성 항목에 대한 참조 정보를 제공해요. 이 구성 항목은 서비스 메시의 프록시에 JWT 검증을 추가하기 위해 JSON Web Token(JWT)과 JSON Web Key Set(JWKS)을 사용하도록 Consul을 구성해요. 자세한 내용은 서비스 인텐션과 함께 JWT 인증 사용을 참고하세요.
구성 모델 (Configuration model)
다음 목록은 JWT 프로바이더 구성 항목의 필드 계층, 언어별 데이터 유형, 요구 사항을 설명해요. 속성 이름을 클릭하면 기본값을 포함한 추가 세부 정보를 볼 수 있어요.
HCL 및 JSON 필드 계층:
Kind: string | 필수 |jwt-provider로 설정해야 함Name: string | 필수Issuer: stringJSONWebKeySet: mapLocal: mapRemote: mapURI: stringRequestTimeoutMs: integerCacheDuration: string |5mFetchAsynchronously: boolean |falseUseSNI: boolean |falseJWKSCluster: mapDiscoveryType: string |STRICT_DNSConnectTimeout: string |5sTLSCertificates: mapCaCertificateProviderInstance: mapInstanceName: string |defaultCertificateName: string
TrustedCA: mapFilename: stringEnvironmentVariable: stringInlineString: stringInlineBytes: string
RetryPolicy: mapNumRetries: integer |0RetryPolicyBackoff: mapBaseInterval: stringMaxInterval: string
Audiences: 문자열 목록Locations: 맵 목록Header: mapName: stringValuePrefix: stringForward: boolean |false
QueryParam: map — [Name]: stringCookie: map — [Name]: string
Forwarding: mapHeaderName: stringPadForwardPayloadHeader: boolean |false
ClockSkewSeconds: integer |30CacheConfig: mapSize: integer |0
YAML 필드 계층: apiVersion(필수, consul.hashicorp.com/v1alpha1), kind(필수, JWTProvider), metadata(필수로 name 필수, namespace 선택), spec(필수), 그리고 spec 아래에 issuer, jsonWebKeySet(local/remote), audiences, locations(header/queryParam/cookie), forwarding, clockSkewSeconds, cacheConfig가 있어요. 각 필드는 위 HCL/JSON과 동일한 의미를 가져요.
완전한 구성 (Complete configuration)
모든 필드가 정의되면 JWT 프로바이더 구성 항목은 다음 형태를 가져요:
HCL
Kind = "jwt-provider" # required
Name = "<name-of-provider-configuration-entry>" # required
Issuer = "<jwt-issuer>" # required
JSONWebKeySet = { # required
Local = { # cannot specify with JWKS{}.Remote
JWKS = "<JWKS-as-base64-string>" # cannot specify with JWKS{}.Local{}.Filename
Filename = "<path/to/JWKS/file>" # cannot specify with JWKS{}.Local{}.String
}
}
JSONWebKeySet = {
Remote = { # cannot specify with JWKS{}.Local
URI = "<uniform-resource-identifier>"
RequestTimeoutMs = 1500
CacheDuration = "5m"
FetchAsynchronously = false
UseSNI = false
RetryPolicy = {
NumRetries = 0
RetryPolicyBackoff = {
BaseInterval = "1s"
MaxInterval = "10s"
}
}
JWKSCluster = {
DiscoveryType = "STATIC"
ConnectTimeout = "10s"
# specify only one child: TrustedCA or CaCertificateProviderInstance
TLSCertificates = {
# specify only one child: Filename, EnvironmentVariable, InlineString or InlineBytes
TrustedCA = {
Filename = "<path/to/cert/file>"
EnvironmentVariable = "<env-variable>"
InlineString = "<inline-string>"
InlineBytes = "\302\000\302\302\302\302"
}
}
TLSCertificates = {
CaCertificateProviderInstance = {
InstanceName = "<instance-name>"
CertificateName = "<certificate-name>"
}
}
}
}
}
Audiences = ["<aud-claims>"]
Locations = [
{
Header = {
Name = "<name-of-header-with-token>"
ValuePrefix = "<prefix-in-header-before-token>"
Forward = false
}
},
{
QueryParam = {
Name = "<name-of-query-parameter-with-token>"
}
},
{
Cookie = {
Name = "<name-of-cookie-with-token>"
}
}
]
Forwarding = {
HeaderName = "<name-appended-to-forwarding-header>"
PadForwardPayloadHeader = false
}
ClockSkewSeconds = 30
CacheConfig = {
Size = 0
}
JSON
{
"Kind": "jwt-provider", // required
"Name": "<name-of-provider-configuration-entry>", // required
"Issuer": "<jwt-issuer>", // required
"JSONWebKeySet": { // required
"Local": { // cannot specify with JWKS.Remote
"JWKS": "<JWKS-as-base64-string>", // cannot specify with JWKS.Local.Filename
"Filename": "<path/to/JWKS/file>" // cannot specify with JWKS.Local.String
}
},
"JSONWebKeySet": {
"Remote": { // cannot specify with JWKS.Local
"URI": "<uniform-resource-identifier>",
"RequestTimeoutMs": "1500",
"CacheDuration": "5m",
"FetchAsynchronously": "false",
"UseSNI": "false",
"RetryPolicy": {
"NumRetries": "0",
"RetryPolicyBackOff": {
"BaseInterval": "1s",
"MaxInterval": "10s"
}
},
"JWKSCluster": {
"DiscoveryType": "STATIC",
"ConnectTimeout": "10s",
// specify only one child: TrustedCA or CaCertificateProviderInstance
"TLSCertificates": {
// specify only one child: Filename, EnvironmentVariable, InlineString or InlineBytes
"TrustedCA": {
"Filename": "<path/to/cert/file>",
"EnvironmentVariable": "<env-variable>",
"InlineString": "<inline-string>",
"InlineBytes": "\302\000\302\302\302\302"
},
},
"TLSCertificates": {
"CaCertificateProviderInstance": {
"InstanceName": "<instance-name>",
"CertificateName": "<certificate-name>"
}
}
}
}
},
"Audiences": ["<aud-claims>"],
"Locations": [
{
"Header": {
"Name": "<name-of-header-with-token>",
"ValuePrefix": "<prefix-in-header-before-token>",
"Forward": "false"
}
},
{
"QueryParam": {
"Name":"<name-of-query-parameter-with-token>",
}
},
{
"Cookie": {
"Name": "<name-of-cookie-with-token>"
}
}
],
"Forwarding": {
"HeaderName": "<name-appended-to-forwarding-header>",
"PadForwardPayloadHeader": "false"
},
"ClockSkewSeconds": "30",
"CacheConfig": {
"Size": "0"
}
}
YAML
apiVersion: consul.hashicorp.com/v1alpha1 # required
kind: JWTProvider # required
metadata: # required
name: <name-of-provider-configuration-entry> # required
namespace: <namespace>
spec: # required
issuer: <jwt-issuer>
jsonWebKeySet:
local: # cannot specify with spec.jsonWebKeySet.remote
jwks: <jwks-as-base64-string> # cannot specify with spec.jsonWebKeySet.local.filename
filename: <path/to/jwks/file> # cannot specify with spec.jsonWebKeySet.local.string
jsonWebKeySet:
remote: # cannot specify with spec.jsonWebKeySet.local
uri: <uniform-resource-identifier>
requestTimeoutMs: 1500
cacheDuration: 5m
fetchAsynchronously: false
useSNI: false
retryPolicy:
numRetries: 0
retryPolicyBackoff:
baseInterval: 1s
maxInterval: 10s
jwksCluster:
discoveryType: STATIC
connectTimeout: 10s
# specify only one child: trustedCA or caCertificateProviderInstance
tlsCertificates:
# specify only one child: filename, environmentVariable, inlineString or inlineBytes
trustedCA:
filename: <path/to/cert/file>
environmentVariable: <env-variable>
inlineString: <inline-string>
inlineBytes: \302\000\302\302\302\302
tlsCertificates:
caCertificateProviderInstance:
instanceName: <instance-name>
certificateName: <certificate-name>
audiences: [<aud-claims>]
locations:
header:
name: <name-of-header-with-token>
valuePrefix: "<prefix-in-header-before-token>"
forward: false
queryParam:
name: "<name-of-query-parameter-with-token>"
cookie:
name: "<name-of-cookie-with-token>"
forwarding:
headerName: "<name-appended-to-forwarding-header>"
padForwardPayloadHeader: false
clockSkewSeconds: 30
cacheConfig:
size: 0
사양 (Specification)
이 섹션은 JWT 프로바이더 구성 항목에서 구성할 수 있는 필드에 대한 세부 정보를 제공해요.
Kind
구현할 구성 항목의 유형을 지정해요.
- 기본값: 없음
- 이 필드는 필수예요.
- 데이터 유형:
jwt-provider로 설정해야 하는 문자열 값.
Name
구성 항목의 이름을 지정해요. 구성 파일의 이름을 구성에 사용되는 JWT 프로바이더의 이름으로 지정할 것을 권장해요. 예시 구성은 Okta JWT Provider 예시를 참고하세요.
- 기본값: 없음
- 이 필드는 필수예요.
- 데이터 유형: String
Issuer
JWT를 발급한 프로바이더를 지정해요. 이 값은 토큰의 iss(발급자) 클레임과 일치해야 해요.
- 기본값: 없음
- 데이터 유형: String
JSONWebKeySet
JSON Web Key Set을 정의해요. 이 필드는 로컬 파일로 구성하거나 원격 서버에서 키 집합을 가져오는 지침을 지정할 수 있어요. 같은 맵에서 [JSONWebKeySet{}.Local]과 [JSONWebKeySet{}.Remote]을 함께 지정할 수 없어요.
- 기본값: 없음
- 데이터 유형: [
Local] 또는 [Remote] 중 하나를 포함할 수 있는 Map.
JSONWebKeySet{}.Local
JSON Web Key Set의 로컬 소스를 지정해요. 소스를 구성 항목의 문자열로 지정하거나 집합을 포함하는 로컬 파일 이름을 포함할 수 있어요. 같은 맵에서 JWKS와 Filename을 함께 지정할 수 없어요.
JSONWebKeySet{}.Local{}.JWKS: JWT 서명을 검증하는 JSON Web Key Set을 base64 인코딩 문자열로 지정해요. 같은 맵에Filename이 지정되면JWKS를 지정할 수 없어요.JSONWebKeySet{}.Local{}.Filename: 로컬 디스크에서 JSON Web Key Set 위치의 경로를 지정해요. 이 필드가 지정되면 이 프로바이더를 참조하는 서비스 인텐션이 있는 모든 프록시에 대해 파일이 디스크에 있어야 해요.
JSONWebKeySet{}.Remote
JSON Web Key Set의 원격 소스를 지정하고 키 집합을 가져올 때의 동작을 구성해요.
URI: JSON Key Web Set을 쿼리할 서버의 URI를 지정해요.RequestTimeoutMs: 원격 URI에 대한 요청이 타임아웃되기 전의 시간(밀리초)을 지정해요.CacheDuration: 캐시된 키가 만료되기 전에 사용할 수 있는 시간을 지정해요. 기본 캐시 기간은 5분이에요. 기본값:5m.FetchAsynchronously: JSON Web Key Set을 클라이언트 요청 도착 전에 가져올지 결정해요. 활성화되면 들어오는 요청 전에 JWKS를 가져와요. 비활성화되면 각 요청 도착 후 JWKS를 가져오며 프록시 리스너는 JWKS가 가져와질 때까지 대기한 후 활성화돼요. 기본값:false.UseSNI: TLS 연결에 호스트 이름을 SNI에 추가할지 결정해요. 기본값:false.RetryPolicy: 원격 위치에서 JSON Web Key Set을 가져올 때 재시도 정책을 정의해요.NumRetries: 이전 시도가 실패했을 때 JSON Web Key Set을 가져오려 시도하는 횟수를 지정해요. 기본값:0.RetryPolicyBackoff: 지터(jittered) 지수 백오프 전략을 지정해요. 이 필드가 비어 있으면 Envoy의 기본 정책(1초 기본 간격, 10초 최대 간격)이 사용돼요. 매개변수:BaseInterval(기본1s),MaxInterval(기본10s).
JWKSCluster: Envoy가 원격 JSON Web Key Set URI를 가져오는 방식을 정의해요.DiscoveryType: 클러스터 해석에 사용할 서비스 디스커버리 유형을 지정해요.STRICT_DNS,STATIC,LOGICAL_DNS,EDS,ORIGINAL_DST를 지정할 수 있어요. 기본값:STRICT_DNS.ConnectTimeout: 클러스터의 호스트에 새 네트워크 연결이 시도하다 타임아웃되기 전의 시간을 지정해요. 기본값:5s.TLSCertificates: 제시된 피어 인증서를 검증하는 데 사용할 인증 기관 인증서가 포함된 데이터를 지정해요. 이 필드가 구성되지 않으면 Envoy는 피어가 제시하는 인증서를 검증하지 않아요.CaCertificateProviderInstance: TLS 인증서를 가져오는 인증서 프로바이더 인스턴스를 지정해요.InstanceName(기본default),CertificateName(예:ROOTCA).TrustedCA: 인증 기관 인증서가 포함된 TLS 인증서 데이터를 지정해요. 정확히 하나의 데이터 소스(Filename,EnvironmentVariable,InlineString,InlineBytes)를 지정해요.
Audiences
JWT가 접근할 수 있는 audience 집합을 aud(audience) 클레임 목록으로 지정해요. 이 필드가 지정되면 프로바이더로 검증된 모든 JWT는 유효한 것으로 간주되려면 최소한 하나의 audience를 대상으로 해야 해요.
- 기본값: 없음
- 데이터 유형: 문자열 목록
Locations
요청에서 JWT를 찾을 위치를 지정해요. Envoy는 JWT를 추출하기 위해 이 모든 위치를 검사해요. 이 필드는 헤더, 쿼리 매개변수, 쿠키에서 토큰 위치를 지정할 수 있어요. 위치가 지정되지 않으면 Envoy는 기본적으로 다음 위치를 사용해요:
- Bearer 스키마가 있는 Authorization 헤더:
"Authorization: Bearer ***" - [
access_token] 쿼리 매개변수.
Locations[].Header: HTTP 요청 헤더에서 JWT를 추출하는 방법을 정의해요.Name: 토큰을 포함하는 HTTP 요청 헤더의 이름을 지정해요.ValuePrefix: 헤더 값에서 토큰 앞에 와야 하는 접두사를 지정해요. 예를 들어Bearer는Authorization: Bearer ***형식인 "Authorization" 헤더의 표준 값 접두사예요. 접두사는 토큰의 일부가 아니에요.Forward: 토큰이 검증된 후 JWT가 있는 헤더를 전달할지 지정해요.false로 설정하면 헤더가 전달되지 않아요. 기본값:false.
Locations[].QueryParam: HTTP 요청 쿼리 매개변수에서 JWT를 추출하는 방법을 정의해요.Name은 토큰을 포함하는 쿼리 매개변수의 이름을 지정해요.Locations[].Cookie: HTTP 요청 쿠키에서 JWT를 추출하는 방법을 정의해요.Name은 토큰을 포함하는 쿠키의 이름을 지정해요.
Forwarding
검증 후 JWT를 백엔드로 전달하는 규칙을 정의해요.
HeaderName: 검증된 JWT를 백엔드로 전달할 때 사용할 헤더 이름을 지정해요. JWT가 추출된 위치를 가정하지 않으며 헤더, 쿼리 매개변수, 쿠키에서 추출된 토큰에 적용될 수 있어요. 헤더 값은 base64 URL 인코딩되며 기본적으로 패딩되지 않아요.PadForwardPayloadHeader:HeaderName에 지정된 base64 인코딩 토큰에 패딩을 추가할지 결정해요. 기본값:false.
ClockSkewSeconds
JSON 웹 토큰의 exp(만료) 및 nbf(not before) 클레임을 검증할 때 허용되는 최대 클록 스큐(clock skew) 시간 차이를 초 단위로 지정해요. 기본값은 30초예요.
- 기본값:
30 - 데이터 유형: Integer
CacheConfig
이전에 만난 JWT의 검증 결과를 캐싱하는 동작을 정의해요. 결과 캐싱은 동일한 토큰이 여러 번 처리될 것으로 예상될 때 검증 속도를 높일 수 있어요. 기본적으로 캐시는 JWT 100개를 담을 수 있어요.
Size: 캐시할 JSON 웹 토큰의 수를 지정해요. 기본값:100.
YAML 전용 필드 (apiVersion, kind, metadata, spec)
apiVersion: Kubernetes와 통합하기 위한 Consul API 버전을 지정해요.consul.hashicorp.com/v1alpha1이어야 해요.kind: 구현할 구성 항목의 유형.jwtProvider로 설정해야 해요.metadata: 구성 항목의 임의 이름과 그것이 적용되는 네임스페이스를 포함하는 맵.name(필수)과namespace(선택)를 포함해요.spec:jwtProvider구성 항목의 세부 정보를 포함하는 맵.apiVersion,kind,metadata필드는 spec 필드의 형제이며 다른 모든 구성은 자식이에요. spec 아래의issuer,jsonWebKeySet,audiences,locations,forwarding,clockSkewSeconds,cacheConfig필드는 각각 위 HCL/JSON의 대응 필드와 동일한 의미를 가져요.
메트릭 (Metrics)
Envoy 프록시는 JWT 인증 세부 정보를 추적할 수 있는 메트릭을 노출해요. 다음 Envoy 메트릭을 사용해요:
http.public_listener.jwt_authn.allowed
http.public_listener.jwt_authn.cors_preflight_bypassed
http.public_listener.jwt_authn.denied
http.public_listener.jwt_authn.jwks_fetch_failed
http.public_listener.jwt_authn.jwks_fetch_success
http.public_listener.jwt_authn.jwt_cache_hit
http.public_listener.jwt_authn.jwt_cache_miss
참고 현재 Envoy는 문서에서 이 메트릭을 참조하지 않아요. 노출된 메트릭에 대한 자세한 내용은 Envoy 문서를 참고하세요.
예시 (Examples)
다음 예시는 특정 사용 사례에 대한 일반적인 JWT 프로바이더 구성 패턴을 보여줘요.
Okta JWT 프로바이더
다음 예시는 Okta가 발급한 JSON 웹 토큰을 가져오도록 Consul을 구성해요. Consul은 URI에서 토큰을 가져오고 토큰이 만료되기 전 30분 동안 캐시에 보관해요. 검증 후 토큰은 user-token을 HTTP 헤더에 추가해 백엔드로 전달돼요.
HCL
Kind = "jwt-provider"
Name = "okta"
Issuer = "okta"
JSONWebKeySet = {
Remote = {
URI = "https://<org>.okta.com/oauth2/default/v1/keys"
CacheDuration = "30m"
}
}
Forwarding = {
HeaderName = "user-token"
}
JSON
{
"Kind": "jwt-provider",
"Name": "okta",
"Issuer": "okta",
"JSONWebKeySet": {
"Remote": {
"URI": "https://<org>.okta.com/oauth2/default/v1/keys",
"CacheDuration": "30m"
}
},
"Forwarding": {
"HeaderName": "user-token"
}
}
YAML
apiVersion: consul.hashicorp.com/v1alpha1
kind: JWTProvider
metadata:
name: okta
spec:
issuer: okta
jsonWebKeySet:
remote:
uri: https://<org>.okta.com/oauth2/default/v1/keys
cacheDuration: 30m
forwarding:
headerName: user-token