OAuth 2.0 클라이언트 자격 증명 인증
본문
Client Credentials
Traefik Hub 기능
이 미들웨어는 Traefik Hub에서만 사용할 수 있어요. Traefik Hub의 고급 기능에 대해 더 알아보세요.
OAuth 2.0 클라이언트 자격 증명 인증 미들웨어는 RFC 6749에 기술된 OAuth 2.0 Client Credentials 플로우를 사용해 Traefik Hub가 경로(route)를 보호할 수 있게 해 줍니다. 접근 토큰은 외부 KV 스토어를 사용해 캐시할 수 있어요.
OAuth 클라이언트 자격 증명 인증 미들웨어는 유효한 동안 접근 토큰을 영속적인 KV 스토어로 사용하기 위해 Redis(또는 Sentinel)를 사용할 수 있어요. 이렇게 하면 대기 시간과 인증 서버로의 호출 횟수를 줄일 수 있습니다.
구성 예시
Middleware OAuth Client Credentials
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-client-creds
spec:
plugin:
oAuthClientCredentials:
url: https://tenant.auth0.com/oauth/token
clientID: urn:k8s:my-secret:my-secret:clientID
clientSecret: urn:k8s:my-secret:my-secret:clientSecret
audience: https://api.example.com
forwardHeaders:
Group: grp
Expires-At: exp
claims: Equals(`grp`, `admin`)
Kubernetes Secret
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: my-secret
stringData:
clientID: my-oauth-client-name
clientSecret: mypasswd
구성 옵션
| Field | Description | Default | Required |
| audience | 인증 서버에 구성된 audience를 정의해요. audience 값은 접근 중인 리소스의 기본 주소입니다(예: https://api.example.com). | "" | Yes |
| claims | 요청을 승인하기 위해 검증할 클레임을 정의해요. claims 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. (자세한 내용은 여기) | "" | No |
| clientConfig.tls.ca | 인증 서버와 TLS 연결을 맺는 데 사용하는 인증서 번들을 담은 PEM 인코딩 인증서 번들이나 비밀을 참조하는 URN (자세한 내용은 여기) | "" | No |
| clientConfig.tls.cert | Vault 서버와 TLS 연결을 맺는 데 사용하는 인증서를 담은 PEM 인코딩 인증서나 비밀을 참조하는 URN (자세한 내용은 여기) | "" | No |
| clientConfig.tls.key | Vault 서버와 TLS 연결을 맺는 데 사용하는 키를 담은 PEM 인코딩 키나 비밀을 참조하는 URN. (자세한 내용은 여기) | "" | No |
| clientConfig.tls.insecureSkipVerify | 인증 서버와 통신할 때 TLS 인증서 검증을 끕니다. 테스트 목적으로는 유용하지만 프로덕션에는 강력히 권장되지 않아요. (자세한 내용은 여기) | false | No |
| clientConfig.timeoutSeconds | 인증 서버에 대한 요청을 포기하기 전의 시간을 정의해요. | 5 | No |
| clientConfig.maxRetries | 실패한 인증 서버 요청에 대한 재시도 횟수를 정의해요. | 3 | No |
| clientID | OpenID Connect 공급자의 계정에 대한 고유 클라이언트 식별자를 정의해요. clientSecret 옵션이 설정되면 반드시 설정해야 해요. 자세한 내용은 여기. | "" | Yes |
| clientSecret | OpenID Connect 공급자의 계정에 대한 고유 클라이언트 비밀을 정의해요. clientID 옵션이 설정되면 반드시 설정해야 해요. 자세한 내용은 여기. | "" | Yes |
| forwardHeaders | 요청에 추가할 HTTP 헤더를 정의하고, 인증 서버가 반환한 접근 토큰 클레임에서 추출한 값으로 채웁니다. JWT에서 찾지 못한 전달 대상 클레임은 빈 헤더가 돼요. forwardHeaders 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. | [] | No |
| store.keyPrefix | 세션을 저장하는 엔트리의 키 접두사를 정의해요. | "" | No |
| store.secret | Redis에 접근 토큰을 저장하는 데 사용하는 암호화 비밀을 정의해요. 16, 24, 32자 중 하나여야 해요. store가 구성되면 필수입니다. | "" | Yes (store가 구성된 경우) |
| store.redis.endpoints | 연결할 Redis 인스턴스의 엔드포인트(예: redis.traefik-hub.svc.cluster.local:6379) | "" | Yes |
| store.redis.username | Traefik Hub가 Redis에 연결할 때 사용하는 사용자 이름 | "" | No |
| store.redis.password | Traefik Hub가 Redis에 연결할 때 사용하는 비밀번호 | "" | No |
| store.redis.database | Traefik Hub가 정보를 저장하는 데 사용할 데이터베이스(기본값: 0) | 0 | No |
| store.redis.cluster | Redis Cluster 모드 활성화. 활성화하려면 {}로 설정하고, 비활성화하려면 생략해요. | - | No |
| store.redis.tls.ca | 커스텀 CA 번들 | "" | No |
| store.redis.tls.cert | TLS 인증서 | "" | No |
| store.redis.tls.key | TLS | "" | No |
| store.redis.tls.insecureSkipVerify | TLS 검증 건너뛰기 허용 | false | No |
| store.redis.sentinel.masterSet | 마스터 선택에 사용할 주 노드 집합의 이름. Sentinel 사용 시 필수. | "" | Yes (Sentinel 사용 시) |
| store.redis.sentinel.username | Sentinel 인증에 사용할 사용자 이름(username과 다를 수 있음) | "" | No |
| store.redis.sentinel.password | Sentinel 인증에 사용할 비밀번호(password와 다를 수 있음) | "" | No |
| url | 인증 서버 URL을 정의해요(예: https://tenant.auth0.com/oauth/token). | "" | Yes |
| usernameClaim | 접근 로그의 clientusername을 채우는 데 평가할 클레임을 정의해요. usernameClaim 옵션은 JWT 형식 토큰에서만 사용할 수 있어요. | "" | No |
Kubernetes secret에 비밀 값 저장하기
Middleware와 같은 네임스페이스에 정의된 Kubernetes secret을 참조할 수 있어요. Kubernetes secret에 대한 참조는 URN 형식을 취합니다:
urn:k8s:secret:[name]:[valueKey]
claims
문법
claims에서 지원하는 함수는 다음과 같아요:
| Function | Description | Example |
| Equals | key의 값이 value와 같은지 검증해요. | Equals(grp, admin) |
| Prefix | key의 값이 value를 접두사로 갖는지 검증해요. | Prefix(referrer, http://example.com) |
| Contains (string) | key의 값이 value를 포함하는지 검증해요. | Contains(referrer, /foo/) |
| Contains (array) | key 배열이 value를 포함하는지 검증해요. | Contains(areas, home) |
| SplitContains | key의 값을 구분자로 나눴을 때 value를 포함하는지 검증해요. | SplitContains(scope, , writer) |
| OneOf | key 배열이 values 중 하나를 포함하는지 검증해요. | OneOf(areas, office, lab) |
모든 함수는 불리언 연산자로 결합할 수 있어요. 지원되는 연산자는 다음과 같아요:
| Operand | Description | Example |
| && | 두 함수를 비교해서 둘 다 참일 때만 참을 반환해요. | Equals(grp, admin) && Equals(active, true) |
| || | 두 함수를 비교해서 둘 중 하나라도 참이면 참을 반환해요. | Equals(grp, admin) || Equals(active, true) |
| ! | 함수가 참이면 false를, 그 외에는 참을 반환해요. | !Equals(grp, testers) |
다음 데이터 구조에서는 모든 예시가 참을 반환해요:
JSON
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
]
}
중첩 클레임 (Nested Claims)
키 사이에 .를 사용해 중첩 클레임을 지원해요. 예를 들어:
Key
user.name
Claims
{
"active": true,
"grp": "admin",
"scope": "reader writer deploy",
"referrer": "http://example.com/foo/bar",
"areas": [
"office",
"home"
],
"user": {
"name": "John Snow",
"status": "undead"
}
}
Result
John Snow
.을 포함하는 키 처리
key에 점이 포함되어 있으면 \.로 이스케이프할 수 있어요.
\를 포함하는 키 처리
key에 \가 포함되어 있으면 \\로 두 번 적어야 합니다.
clientConfig
API 게이트웨이를 Identity Provider 같은 서드파티 소프트웨어에 연결하는 데 사용하는 구성을 정의해요.
clientConfig.tls
Kubernetes secret에 비밀 값 저장하기
tls.ca, tls.cert, tls.key를 구성할 때, Middleware와 같은 네임스페이스에 정의된 Kubernetes secret을 참조할 수 있어요. Kubernetes secret에 대한 참조는 URN 형식을 취합니다:
urn:k8s:secret:[name]:[valueKey]
Middleware JWT
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: test-client-creds
spec:
plugin:
oAuthClientCredentials:
clientConfig:
tls:
ca: "urn:k8s:secret:tls:ca"
cert: "urn:k8s:secret:tls:cert"
key: "urn:k8s:secret:tls:key"
insecureSkipVerify: true
Kubernetes TLS Secret
apiVersion: v1
kind: Secret
metadata:
name: tls
stringData:
ca: |-
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
cert: |-
-----BEGIN CERTIFICATE-----
MIIB9TCCAWACAQAwgbgxGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHDAaBgNV
BAsME0RvY3VtZW50IERlcGFydG1lbnQxOTA3BgNVBAMMMFdoeSBhcmUgeW91IGRl
Y29kaW5nIG1lPyAgVGhpcyBpcyBvbmx5IGEgdGVzdCEhITERMA8GA1UEBwwISGFt
aWx0b24xETAPBgNVBAgMCFBlbWJyb2tlMQswCQYDVQQGEwJCTTEPMA0GCSqGSIb3
DQEJARYAMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCJ9WRanG/fUvcfKiGl
EL4aRLjGt537mZ28UU9/3eiJeJznNSOuNLnF+hmabAu7H0LT4K7EdqfF+XUZW/2j
RKRYcvOUDGF9A7OjW7UfKk1In3+6QDCi7X34RE161jqoaJjrm/T18TOKcgkkhRzE
apQnIDm0Ea/HVzX/PiSOGuertwIDAQABMAsGCSqGSIb3DQEBBQOBgQBzMJdAV4QP
Awel8LzGx5uMOshezF/KfP67wJ93UW+N7zXY6AwPgoLj4Kjw+WtU684JL8Dtr9FX
ozakE+8p06BpxegR4BR3FMHf6p+0jQxUEAkAyb/mVgm66TyghDGC6/YkiKoZptXQ
98TwDIK/39WEB/V607As+KoYazQG8drorw==
-----END CERTIFICATE-----
key: |-
[REDACTED PRIVATE KEY]
store.redis
Redis 서버에 대한 연결 파라미터는 Middleware 배포에 첨부됩니다.
다음 Redis 모드가 지원됩니다:
-
단일 인스턴스 모드
-
Redis Cluster
-
Redis Sentinel
Info
Redis를 단일 인스턴스 모드나 Redis Sentinel로 사용한다면 database 필드를 구성할 수 있어요. 이 값은 Redis Cluster를 사용하면 고려되지 않습니다(데이터베이스 0만 사용 가능). 이 경우 경고가 표시되고 값은 무시됩니다.
Redis에 대한 자세한 내용은 공식 Redis 문서를 권장합니다.
Traefik OSS를 프로덕션에서 사용하시나요?
직장에서 Traefik을 사용한다면, 엔터프라이즈급 API 게이트웨이 기능이나 Traefik OSS 상용 지원을 추가하는 것을 고려해 보세요.
-
API Gateway 데모 영상 보기
-
24/7/365 OSS 지원 요청
Traefik OSS에 API 게이트웨이 기능을 추가하는 것은 빠르고 매끄러워요. 기존 구성을 교체하거나(rip and replace) 버릴 필요 없이 그대로 유지됩니다. 짧은 영상으로 직접 확인해 보세요.