주:
- 이 사용지침서에서는 Oracle Cloud에 액세스해야 합니다. 무료 계정에 등록하려면 Oracle Cloud Infrastructure Free Tier 시작하기를 참조하십시오.
- Oracle Cloud Infrastructure 인증서, 테넌시 및 구획에 대한 예제 값을 사용합니다. 실습을 마칠 때는 이러한 값을 클라우드 환경과 관련된 값으로 대체하십시오.
Nginx 수신 컨트롤러, OAuth2 프록시 및 Oracle ID 도메인을 사용하여 Kubernetes 웹 서비스 보호
소개
Kubernetes 호스팅 웹 서비스 보안은 쉬워야 합니다. 애플리케이션에 외부 ID 제공자(IdP) 통합에 대한 기본 제공 지원이 없거나 관리를 단순화하고 서비스당 개별 인증 방식의 필요성을 줄이기 위해 SSO(Single Sign-On) 솔루션이 필요한 경우 OAuth2 프록시는 모든 애플리케이션을 거의 모든 ID 제공자(IdP)에 연결할 수 있는 유연성을 제공합니다.
OAuth2 프록시는 Kubernetes 서비스 앞에 있는 역 프록시 역할을 합니다. 트래픽을 가로채고, 로그인을 위해 사용자를 외부 권한 부여 서버(예: Okta 또는 GitHub)로 재지정하고, 백엔드 서비스로 요청을 전달하기 전에 액세스 토큰을 검증합니다.
목표
- 간단한 웹 애플리케이션을 Kubernetes에 배치하고, Nginx 수신 컨트롤러를 사용하여 노출하고, Oracle Identity Domains를 IdP로 사용하도록 OAuth2 프록시를 구성합니다.
필요 조건
-
OCI(Oracle Cloud Infrastructure) 테넌시에 액세스합니다.
-
로드 밸런서에 공용 서브넷을 사용하도록 구성된 OKE(Oracle Cloud Infrastructure Container Engine for Kubernetes) 클러스터입니다.
-
(선택사항) DNS(도메인 이름 시스템) 도메인의 레코드를 업데이트하기 위한 액세스 권한입니다.
작업 1: OKE 클러스터 만들기
-
OCI 콘솔에 로그인하고 Oracle Container Engine for Kubernetes로 이동한 후 생성을 누릅니다.
-
클러스터 생성 마법사에서 빠른 생성을 누릅니다.
-
아래와 같은 정보를 입력하고 다음을 누릅니다.
- 이름: 클러스터 이름을 입력합니다.
- Kubernetes 버전: 사용할 버전을 선택합니다.
- Kubernetes API 엔드포인트: 공용 엔드포인트를 선택합니다.
- 노드 유형: 관리됨을 선택합니다.
- Kubernetes 워커 노드: 전용 워커를 선택합니다.
- 코드 수:
1
.
-
Create Cluster를 검토하고 누릅니다. 클러스터가 사용 가능해질 때까지 기다립니다.
-
서비스 서브넷과 연관된 보안 목록을 업데이트합니다.
-
서비스 서브넷을 누릅니다.
-
보안 목록을 누르고 다음 규칙을 추가합니다.
-
수신:
-
송신:
-
-
-
로드 밸런서로부터의 접속을 허용하도록 워커 노드 서브넷과 연관된 보안 목록을 업데이트합니다.
-
VCN 이름을 누릅니다.
-
Resources 아래에서 Security Lists를 선택하고 노드 보안 목록을 누릅니다.
-
노드 보안 목록에 다음 수신 규칙을 추가합니다.
-
수신 규칙 추가를 누릅니다.
-
작업 2: Nginx 수신 컨트롤러 설정
-
클러스터를 사용할 수 있게 되면 OCI Cloud Shell을 사용하여 클러스터에 액세스할 수 있습니다. 클러스터 액세스를 누르고 OCI Cloud Shell에서 다음 명령을 복사하여 실행합니다.
-
kubectl get node
명령을 실행하여 사용 가능한 노드 목록을 가져옵니다. -
Nginx Ingress Controller Helm 저장소를 추가합니다. 자세한 내용은 Overview of Ingress NGINX Controller 및 helm를 참조하십시오.
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm repo update
-
values-override.yaml
파일을 만듭니다.controller: allowSnippetAnnotations: true service: annotations: oci.oraclecloud.com/load-balancer-type: "lb" service.beta.kubernetes.io/oci-load-balancer-backend-protocol: "TCP" service.beta.kubernetes.io/oci-load-balancer-shape: "flexible" service.beta.kubernetes.io/oci-load-balancer-shape-flex-min: "10" service.beta.kubernetes.io/oci-load-balancer-shape-flex-max: "10"
-
Nginx 수신 컨트롤러를 배치합니다.
helm install ingress-nginx ingress-nginx/ingress-nginx -f values-override.yaml
-
application.yaml
라는 다음yaml
파일을 저장합니다.--- # Create ClusterIP service apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin spec: ports: - port: 5000 targetPort: 5000 selector: app: httpbin --- # Deployment of a sample web application apiVersion: apps/v1 kind: Deployment metadata: name: httpbin spec: replicas: 2 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 spec: containers: - image: mendhak/http-https-echo imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 5000 env: - name: HTTP_PORT value: "5000"
-
응용 프로그램 리소스를 만듭니다.
kubectl apply -f application.yaml
-
로드 밸런서와 연관된 공용 IP 주소에 대한 DNS 레코드를 생성합니다.
-
로드 밸런서의 공용 IP 주소를 가져옵니다.
$ kubectl get svc ingress-nginx-controller NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-controller LoadBalancer 10.96.152.30 158.180.61.74 80:31957/TCP,443:30838/TCP 32s
-
DNS 레코드를 만듭니다. DNS 서버가 없는 경우 무료 와일드카드 DNS 서비스 nip.io를 사용합니다.
이 경우 FQDN은
158-180-61-74.nip.io
입니다. -
-
ingress.yaml
라는 다음yaml
파일을 저장합니다.주: FQDN으로 호스트 항목을 업데이트해야 합니다.
--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: httpbin-ingress-nginx spec: ingressClassName: nginx tls: - hosts: - "<YOUR-FQDN>" rules: - host: "<YOUR-FQDN>" http: paths: - pathType: Prefix path: "/" backend: service: name: httpbin port: number: 5000
-
다음 명령을 실행하여 수신 리소스를 만듭니다.
kubectl apply -f ingress.yaml
-
서비스에 대한 접속을 테스트합니다.
$ curl -k https://<YOUR-FQDN> { "path": "/", "headers": { "host": "158-180-61-74.nip.io", "x-request-id": "b0320217391a922acecbfe10758b3ffe", "x-real-ip": "10.0.10.167", "x-forwarded-for": "10.0.10.167", "x-forwarded-host": "158-180-61-74.nip.io", "x-forwarded-port": "443", "x-forwarded-proto": "https", "x-forwarded-scheme": "https", "x-scheme": "https", "user-agent": "curl/7.87.0", "accept": "*/*" }, "method": "GET", "body": "", "fresh": false, "hostname": "158-180-61-74.nip.io", "ip": "10.0.10.167", "ips": [ "10.0.10.167" ], "protocol": "https", "query": {}, "subdomains": [ "158-180-61-74" ], "xhr": false, "os": { "hostname": "httpbin-644874bcdb-ll4mb" }, "connection": {} }
작업 3: Oracle Identity Domains에서 기밀 애플리케이션 설정
-
OCI 콘솔에서 Oracle Identity Domains로 이동하고
OracleIdentityCloudService
도메인을 누릅니다. -
왼쪽 메뉴에서 통합 애플리케이션을 선택하고 애플리케이션 추가를 누릅니다.
-
기밀 애플리케이션을 선택하고 워크플로우 실행을 누릅니다.
-
애플리케이션 이름, 설명을 입력하고 다음을 누릅니다.
-
애플리케이션 oAuth 매개변수를 구성합니다.
-
권한 부여 섹션에서 권한 부여 코드를 선택합니다.
-
다음 URL을 입력하고 다음을 누릅니다.
- 재지정 URL:
https://<YOUR-FQDN>/oauth2/callback
. - 사후 로그아웃 재지정 URL:
https://<YOUR-FQDN>
. - 로그아웃 URL:
https://<YOUR-FQDN>/oauth2/sign_out
.
- 재지정 URL:
-
-
웹 계층 정책에서 건너뛰기 후 나중에 수행을 선택하고 완료를 누릅니다.
-
활성화를 눌러 애플리케이션을 사용으로 설정합니다.
-
왼쪽 메뉴에서 그룹으로 이동하여 이 애플리케이션에 인증할 수 있는 사용자 그룹을 연관시킵니다.
-
고객 ID 및 고객 암호를 적어둡니다.
-
OracleIdentityCloudService 도메인을 누르고 도메인 URL을 확장합니다.
예: ID 도메인 URL은
https://idcs-01234567890abcdef.identity.oraclecloud.com
입니다(포트 번호 제거).
작업 4: OAuth2 프록시 배치
OAuth2 프록시를 사용하여 OAuth2 또는 OIDC(OpenID Connect) 복잡성을 처리하고 애플리케이션으로 전달된 모든 요청이 인증되었는지 확인합니다.
-
oauth2-proxy.yaml
라는 다음yaml
파일을 저장하고 위치 표시자를 적용 가능한 값으로 바꿉니다.참고:
-
<Identity Domain URL>
:https://idcs-01234567890abcdef.identity.oraclecloud.com/
-
<Identity Domain FQDN>
:idcs-01234567890abcdef.identity.oraclecloud.com
--- apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: oauth2-proxy name: oauth2-proxy spec: replicas: 1 selector: matchLabels: k8s-app: oauth2-proxy template: metadata: labels: k8s-app: oauth2-proxy spec: containers: - args: - --provider=oidc - --provider-display-name="Oracle Identity Domains" - --oidc-issuer-url=<Identity Domain URL> - --redirect-url=https://<YOUR-FQDN>/oauth2/callback - --upstream=file:///dev/null - --http-address=0.0.0.0:4180 - --email-domain=* - --set-xauthrequest=true - --session-cookie-minimal=true - --whitelist-domain=<Identity Domain FQDN> env: - name: OAUTH2_PROXY_CLIENT_ID value: "<APPLICATION_CLIENT_ID>" - name: OAUTH2_PROXY_CLIENT_SECRET value: "<APPLICATION_CLIENT_SECRET>" # docker run -ti --rm python:3-alpine python -c 'import secrets,base64; print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))));' - name: OAUTH2_PROXY_COOKIE_SECRET value: "<OUTPUT_OF_THE_ABOVE_DOCKER_COMMAND>" image: quay.io/oauth2-proxy/oauth2-proxy:latest imagePullPolicy: Always name: oauth2-proxy ports: - containerPort: 4180 protocol: TCP --- apiVersion: v1 kind: Service metadata: labels: k8s-app: oauth2-proxy name: oauth2-proxy spec: ports: - name: http port: 4180 protocol: TCP targetPort: 4180 selector: k8s-app: oauth2-proxy --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: oauth2-proxy annotations: nginx.ingress.kubernetes.io/configuration-snippet: | set $xheader ""; if ( $request_uri = "/oauth2/sign_out" ){ set $xheader "https://<Identity Domain FQDN>/oauth2/v1/userlogout; } proxy_set_header X-Auth-Request-Redirect ${xheader}; spec: ingressClassName: nginx rules: - host: <YOUR-FQDN> http: paths: - path: /oauth2 pathType: Prefix backend: service: name: oauth2-proxy port: number: 4180 tls: - hosts: - <YOUR-FQDN>
-
-
OKE에 OAuth2 프록시를 배치합니다.
kubectl apply -f oauth2-proxy.yaml
Pod가 실행 중인지 확인합니다.
kubectl get pods -l k8s-app=oauth2-proxy
-
요청 인증에 OAuth2 프록시를 사용하도록 Nginx를 구성합니다.
auth annotation을 사용하여
ingress.yaml
파일을 업데이트합니다.--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: httpbin-ingress-nginx annotations: nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri" nginx.ingress.kubernetes.io/auth-response-headers: "x-auth-request-user, x-auth-request-email" spec: ingressClassName: nginx tls: - hosts: - "<YOUR-FQDN>" rules: - host: "<YOUR-FQDN>" http: paths: - pathType: Prefix path: "/" backend: service: name: httpbin port: number: 5000
-
응용 프로그램에 연결해 봅니다. Oracle 인증 페이지로 재지정되어야 합니다. 인증이 성공하면 애플리케이션으로 재지정되어야 합니다.
인증된 사용자를 식별하는 두 개의 헤더가 있습니다.
"x-auth-request-user": "xxxx@oracle.com" "x-auth-request-email": "xxxx@oracle.com"
-
애플리케이션에서 사인아웃하려면 페이지의
/oauth2/sign_out
으로 이동할 수 있습니다.https://<YOUR-FQDN>/oauth2/sign_out
알려진 문제: 사후 사인아웃 재지정이 작동하지 않습니다. 이 문제는 OIDC 제공자에 대한 로그아웃 제공자 URL에 id_token_hint 매개변수 추가에서 추적됩니다.
작업 5: 리소스 정리
-
다음 명령을 실행하여 모든 Kubernetes 배치된 리소스를 삭제합니다.
kubectl delete -f oauth2-proxy.yaml -f ingress.yaml -f application.yaml helm uninstall ingress-nginx
-
Oracle Identity Domains에서 응용 프로그램을 삭제합니다.
-
OKE 클러스터를 삭제합니다.
-
OKE 클러스터에 대해 생성된 VCN을 삭제합니다.
참고:
-
OKE 클러스터 및 노드 풀 삭제가 종료될 때까지 기다려야 합니다.
-
VCN 이름에는 OKE 클러스터의 이름이 포함됩니다.
oke-vcn-quick-<oke-cluster-name>-<random-string>
.
-
관련 링크
확인
- 작성자 - Andrei Ilas(주요 클라우드 아키텍트)
추가 학습 자원
docs.oracle.com/learn에서 다른 실습을 살펴보거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하십시오. 또한 education.oracle.com/learning-explorer를 방문하여 Oracle Learning Explorer가 되십시오.
제품 설명서는 Oracle Help Center를 참조하십시오.
Secure Kubernetes Web Services using Nginx Ingress Controller, OAuth2 Proxy, and Oracle Identity Domains
F96456-01
April 2024