저희는 오늘날과 같이 랜섬웨어와 봇 기반 공격이 빈번한 환경에서 앱과 API를 보호하는 것이 얼마나 중요한지 여러 차례 강조해 왔습니다. 웹 애플리케이션 방화벽(WAF)과 같은 보안 메커니즘뿐만 아니라, 사용자 신원을 인증하고 권한 부여 제어를 적용하는 것도 비즈니스 애플리케이션을 보호하는 중요한 방법입니다.
인증과 권한 부여를 구현하는 가장 직접적인 방법은 애플리케이션 자체에서 처리하는 것입니다. 사용자 기반이 작고 앱을 자주 업데이트할 필요가 없다면 이 방법도 효과가 있지만, 규모가 커지면 금세 감당하기 어려워집니다. 예를 들어 사용자가 여러 앱마다 서로 다른 계정 이름과 비밀번호를 기억해야 하면 로그인할 때마다 짜증 나는 “사용자 이름 또는 비밀번호가 올바르지 않습니다”라는 메시지를 접하기 쉽고, 결국 쉽게 추측할 수 있는 “abc123” 같은 안전하지 않은 비밀번호를 사용하게 됩니다. 비밀번호를 적은 Post‑it® 메모지가 모니터 주변을 빙 둘러싼 모습도 누구나 한 번쯤 본 적이 있을 것입니다!
SSO(Single Sign-On) 기술은 여러 개의 개별 사용자 이름과 비밀번호를 하나의 자격 증명으로 통합하여 이러한 문제를 어느 정도 해결할 수 있습니다. 사용자는 ID 공급자(IdP)를 통해 한 번만 로그인하면 여러 앱에 액세스할 수 있습니다. 하지만 개발자는 여전히 앱에 SSO 시스템과 연동하기 위한 코드를 포함해야 하며, 특히 애플리케이션이 복잡해질수록 이는 매우 어려운 작업이 될 수 있습니다.
조직이 성장하고 급증하는 사용자 기반의 요구 사항을 충족해야 할수록 인증 및 권한 부여처럼 앱 기능에만 국한되지 않는 요구 사항을 애플리케이션 계층에서 분리하는 것이 중요해집니다. 중앙 집중식 인증 및 권한 부여를 구현하기에 이상적인 위치는 Kubernetes의 인그레스 컨트롤러입니다. 인그레스 컨트롤러는 클러스터로 들어오는 모든 트래픽을 검사하여 적절한 서비스로 라우팅할 수 있습니다. 이를 통해 개발자는 인증 로직을 구축하고 유지 관리하며 복제해야 하는 부담에서 벗어날 수 있으며, 네이티브 Kubernetes API를 사용해 인그레스 계층에서 SSO 기술을 손쉽게 활용할 수 있습니다.
이 블로그에서는 NGINX Plus 기반 NGINX Ingress Controller를 중계 당사자로 사용하여 완전한 SSO 솔루션을 구현하는 방법을 소개합니다. 이 솔루션은 OIDC 인증 코드 흐름을 지원하며, Okta가 사전 구성된 ID 공급자(IdP)로 사용됩니다.
참고: 이 기능은 NGINX Open Source 기반 NGINX Ingress Controller에서는 사용할 수 없습니다.
사전 요구 사항
이 블로그에서는 Kubernetes 환경을 운영해 본 경험이 있다고 가정합니다. 또한 다음 사항이 필요합니다:
- Kubernetes 환경 – NGINX Ingress Controller는 기본 Kubernetes뿐만 아니라 Amazon Elastic Kubernetes(EKS), 베어 메탈, Google Kubernetes Engine(GKE), Microsoft Azure Kubernetes Service(AKS), Rancher Kubernetes Engine, Red Hat OpenShift를 비롯한 다양한 Kubernetes 플랫폼을 지원합니다.
- NGINX Plus 기반 NGINX Ingress Controller – NGINX Ingress Controller의 NGINX Plus 기반 버전을 사용하려면 유효한 라이선스가 있어야 합니다. 지금 30일 무료 평가판을 신청하여 라이선스 사용을 시작할 수 있습니다. 자세한 내용은 설명서를 참조하세요.
- Okta 개발자 계정 – Okta를 IdP로 구성하려면 먼저 개발자 계정에 가입하세요. 또는 Okta 명령줄 인터페이스(CLI)를 다운로드하고
oktaregister명령을 실행하여 새 계정에 가입할 수 있습니다. 이 글을 작성하는 시점에 Okta CLI는 베타 버전이므로 프로덕션 환경에서 사용하는 것은 권장되지 않습니다.
IdP 사전 구성
클라우드 서비스는 사용자 ID를 어디에서 가져와 검증해야 하는지 알아야 하므로 IdP가 필요합니다. IdP는 디지털 ID를 안전하게 관리하고 저장하며, 공격자가 ID를 탈취해 사용자를 사칭하지 못하도록 합니다.
이 섹션에서는 Okta CLI를 사용하여 Okta를 IdP로 미리 구성하고, Okta에서 앱 통합이라고 부르는 것을 생성합니다.
- Run the
oktalogin명령을 실행하여 Okta 개발자 계정으로 Okta CLI를 인증합니다. 메시지가 표시되면 Okta 도메인과 API 토큰을 입력합니다.
$ okta login Okta Org URL: https://your-okta-domain
Okta API token: your-api-token- 앱 통합을 생성합니다:
$ okta apps create --app-name=mywebapp --redirect-uri=http[s]://ingress-controller-hostname/_codexch- 여기서
--app-name은 애플리케이션 이름을 정의합니다(여기서는 mywebapp).--redirect-uri는 로그인이 리디렉션되는 URI를 정의합니다(여기서는 ingress-controller-hostname/_codexch).
- 프롬프트에 따라 애플리케이션 유형을 지정합니다. 먼저 1(웹 애플리케이션을 나타냄)을 입력한 다음 5(목록에 없는 프레임워크를 나타냄)를 입력합니다.
Type of Application
(The Okta CLI only supports a subset of application types and properties):
> 1: Web
> 2: Single Page App
> 3: Native App (mobile)
> 4: Service (Machine-to-Machine)
Enter your choice [Web]: 1
Type of Application
> 1: Okta Spring Boot Starter
> 2: Spring Boot
> 3: JHipster
> 4: Quarkus
> 5: Other
Enter your choice [Other]: 5
Configuring a new OIDC Application, almost done:
Created OIDC application, client-id: 0oa1mi...OrfQAg5d7NGINX Ingress Controller 구성하기
NGINX Plus 기반 버전의 NGINX Ingress Controller를 사용자 인증을 수행하는 릴레이 당사자로 구성합니다.
클라이언트 자격 증명 시크릿 정의
보안상의 이유로 OIDC 정책 객체에 클라이언트 시크릿을 하드코딩하는 것은 지원되지 않습니다. 대신 클라이언트 시크릿 값을 base64로 인코딩한 데이터가 포함된 Kubernetes Secret을 생성합니다.
apiVersion: v1
kind: Secret
metadata:
name: oidc-secret
type: nginx.org/oidc
data:
client-secret: base64-encoded-value-of-client-secret 그런 다음 Secret이 포함된 YAML 파일(여기서는 client-secret.yaml)을 적용합니다:
$ kubectl apply –f client-secret.yaml인증 엔드포인트 가져오기
Okta의 권한 부여 서버에 공개된 엔드포인트에 대한 정보를 가져오려면 OAuth 2.0 및 OpenID Connect API를 사용하세요.
로컬 머신에서 다음 명령어를 실행하여 Okta 엔드포인트에 대한 정보를 출력합니다. 샘플 출력에 표시된 authorization_endpoint, token_endpoint, jwks_uri 값을 기록해 둡니다. 이 값들은 다음 섹션에서 사용합니다.
$ curl -i https://your-okta-domain/.well-known/openid-configuration
{
"authorization_endpoint": "https://your-okta-domain/oauth2/v1/authorize",
...
"jwks_uri": "https://your-okta-domain/oauth2/v1/keys",
...
"token_endpoint": "https://your-okta-domain/oauth2/v1/token",
...
}NGINX Ingress OIDC 정책 정의
NGINX Ingress Controller 1.10.0에 OIDC 기반 인증 지원이 추가되었습니다. 자세한 내용은 블로그의 OpenID Connect와 NGINX Ingress Controller를 활용한 간편하고 강력한 싱글 사인온을 참조하세요.
NGINX Ingress Controller의 OIDC 인증 구현에서는 Kubernetes의 Policy 객체, 즉 NGINX Ingress Controller에서 OIDC 정책을 정의하는 사용자 정의 리소스를 사용합니다.
- 이전 섹션에서 얻은 정보를
authEndpoint,tokenEndpoint,jwksURI필드에 입력합니다. 대상은Policy객체입니다.
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: oidc-policy
spec:
oidc:
clientID: client-id
clientSecret: oidc-secret
authEndpoint: https://your-okta-domain/oauth2/v1/authorize
tokenEndpoint: https://your-okta-domain/oauth2/v1/token
jwksURI: https://your-okta-domain/oauth2/v1/keys- 정책을 적용합니다(여기서는 oidc.yaml에 정의됨):
$ kubectl apply -f oidc.yaml- (선택 사항) 정책의 유효성을 확인합니다:
$ kubectl get policy
NAME STATE AGE
oidc-policy Valid 2mVirtualServer 객체 정의
VirtualServer와 VirtualServerRoute는 NGINX Ingress 리소스로, Kubernetes 클러스터에서 수신 트래픽을 백엔드 애플리케이션으로 라우팅하기 위한 규칙을 제공합니다. OIDC 정책을 적용하려면 VirtualServer 또는 VirtualServerRoute 리소스에서 해당 정책을 참조해야 합니다.
- Reference an OIDC policy under the / 경로 접두사 아래에서 OIDC 정책을 참조하여, 해당 접두사와 일치하는 경로를 요청하는 사용자가 요청이
app-server-payload서비스로 프록시되기 전에 인증되도록 합니다.
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: app-ingress
spec:
host: unit-demo.linkpc.net
upstreams:
- name: app-server-payload
service: app-server-svc
port: 80
routes:
- path: /
policies:
- name: oidc-policy
action:
proxy:
upstream: app-server-payload- VirtualServer 리소스를 적용합니다(여기서는 app-virtual-server.yaml에 정의됨):
$ kubectl apply -f app-virtual-server.yaml- (선택 사항) 리소스의 유효성을 확인합니다:
$ kubectl get vs
NAME STATE HOST IP PORTS AGE
app-ingress Valid unit-demo.linkpc.net 2m환경 테스트
OIDC Okta 통합이 올바르게 작동하는지 테스트하려면 브라우저의 주소 표시줄에 NGINX Ingress Controller의 호스트 이름을 입력합니다. 그러면 Okta 로그인 포털로 리디렉션되며, 여기에서 Okta 개발자 계정의 자격 증명을 입력하여 백엔드 애플리케이션에 액세스할 수 있습니다.

인증에 성공하면 app-server-payload 업스트림 서비스에 액세스할 수 있습니다.
애플리케이션에 사용자 추가
대부분의 경우 조직 내 여러 사용자가 앱에 액세스해야 합니다. Okta 관리 콘솔의 사용자 페이지에서 디렉터리 카테고리 아래에 각 사용자를 추가하세요.

여러 앱을 위한 SSO 통합 만들기
Okta를 IdP로, NGINX Ingress Controller를 중계 당사자로 사용하여 SSO를 구성함으로써 한 애플리케이션의 인증 프로세스를 외부로 이전했습니다. 실제로는 사용자가 하나의 자격 증명 세트로 여러 애플리케이션에 액세스할 수 있도록 설정하고 싶을 것입니다. 또한 사용자별로 액세스할 수 있는 애플리케이션을 유연하게 지정하고 싶을 수도 있습니다. 이렇게 하려면 위 섹션의 지침을 반복해서 수행하세요:
- IdP 사전 구성을 통해 다른 애플리케이션을 Okta와 통합
- NGINX Ingress OIDC 정책 정의를 통해 다른 OIDC 정책 정의
- VirtualServer 객체 정의 - 추가 정책 참조
다음 다이어그램에 표시된 예에는 unit-demo.marketing.net 및 unit-demo.engineering.net이라는 두 개의 하위 도메인이 있으며, 이들은 NGINX Ingress Controller의 외부 IP 주소로 확인됩니다. NGINX Ingress Controller는 하위 도메인에 따라 요청을 마케팅 앱 또는 엔지니어링 앱으로 라우팅합니다. 사용자에게 액세스 권한을 부여하려면 Okta GUI의 할당 탭에서 사용자를 적절한 각 애플리케이션에 연결합니다. 그러면 Okta는 인증된 사용자에게 해당 애플리케이션에 액세스할 수 있는 단기 세션 쿠키를 부여합니다.

결론
NGINX Ingress Controller를 중계 당사자로, Okta를 IdP로 사용하여 Kubernetes에서 OIDC 기반 SSO를 구현하면 개발자가 인증 및 권한 부여를 직접 처리할 필요가 없어져 앱의 비즈니스 로직을 최적화하는 데 집중할 수 있습니다. NGINX Plus 기반 NGINX Ingress Controller를 시작하려면 지금 30일 무료 평가판을 신청하거나 사용 사례에 대해 논의하려면 문의해 주세요.
작성자 소개
관련 블로그 게시물
시청하기: KubeCon North America 2023에서의 NGINX Gateway Fabric
이 영상에서는 KubeCon의 NGINX 부스를 찾아가, 저희가 공개한 Kubernetes Gateway API 구현을 살펴봅니다.
F5 NGINX로 대규모 WAF 플릿을 확인하고 관리하는 2가지 방법
앱 보안을 강화하는 두 가지 방법을 소개합니다. NGINX Management Suite를 통해 WAF 운영에 대한 가시성을 높이고, NGINX App Protect WAF를 활용해 코드형 보안을 구현하는 것입니다.
Ingress 컨트롤러 선택 가이드, 4부: NGINX Ingress Controller 옵션
개발 주체, 개발 철학, 프로덕션 환경 준비도, 보안 및 지원을 기준으로 어떤 NGINX Ingress 컨트롤러가 가장 적합한지 알아보세요.
진화하는 공격 환경에 NGINX App Protect Denial of Service가 적응하는 방법
NGINX App Protect Denial of Service(DoS)가 계층 7 DoS 공격을 방어하기 위해 완화 방법을 실시간으로 조정하는 방식을 설명합니다. 정상적인 사용자 행동과 서버 상태에 대한 모델을 생성하여 공격을 나타내는 이상 징후를 감지하고 맞춤형 완화 시그니처를 적용할 수 있습니다.
NGINX Instance Manager를 활용한 대규모 구성 업데이트 및 인증서 관리
NGINX Instance Manager 버전 1.0에는 두 가지 새로운 기능이 도입되었습니다. NGINX 인스턴스에 태그와 사용자 역할을 지정하면 전체 그룹에 구성을 한 번에 적용할 수 있습니다. 인증서 검사는 만료 예정인 인증서를 감지하여 서비스 중단을 방지할 수 있도록 인증서를 교체할 수 있게 해줍니다.
Netflix가 자사 CDN의 핵심으로 NGINX를 선택한 이유
Netflix가 글로벌 콘텐츠 전송 네트워크인 Open Connect의 스트리밍 미디어 기술로 NGINX를 선택한 이유를 NGINX 개발자 Gleb Smirnoff에게서 알아보세요.
