주:

Nginx 수신 컨트롤러, OAuth2 프록시 및 Oracle ID 도메인을 사용하여 Kubernetes 웹 서비스 보호

소개

Kubernetes 호스팅 웹 서비스 보안은 쉬워야 합니다. 애플리케이션에 외부 ID 제공자(IdP) 통합에 대한 기본 제공 지원이 없거나 관리를 단순화하고 서비스당 개별 인증 방식의 필요성을 줄이기 위해 SSO(Single Sign-On) 솔루션이 필요한 경우 OAuth2 프록시는 모든 애플리케이션을 거의 모든 ID 제공자(IdP)에 연결할 수 있는 유연성을 제공합니다.

OAuth2 프록시는 Kubernetes 서비스 앞에 있는 역 프록시 역할을 합니다. 트래픽을 가로채고, 로그인을 위해 사용자를 외부 권한 부여 서버(예: Okta 또는 GitHub)로 재지정하고, 백엔드 서비스로 요청을 전달하기 전에 액세스 토큰을 검증합니다.

목표

필요 조건

작업 1: OKE 클러스터 만들기

  1. OCI 콘솔에 로그인하고 Oracle Container Engine for Kubernetes로 이동한 후 생성을 누릅니다.

  2. 클러스터 생성 마법사에서 빠른 생성을 누릅니다.

    빠른 생성

  3. 아래와 같은 정보를 입력하고 다음을 누릅니다.

    • 이름: 클러스터 이름을 입력합니다.
    • Kubernetes 버전: 사용할 버전을 선택합니다.
    • Kubernetes API 엔드포인트: 공용 엔드포인트를 선택합니다.
    • 노드 유형: 관리됨을 선택합니다.
    • Kubernetes 워커 노드: 전용 워커를 선택합니다.
    • 코드 수: 1.

    클러스터 생성

  4. Create Cluster를 검토하고 누릅니다. 클러스터가 사용 가능해질 때까지 기다립니다.

  5. 서비스 서브넷과 연관된 보안 목록을 업데이트합니다.

    1. 서비스 서브넷을 누릅니다.

      서비스 서브넷

    2. 보안 목록을 누르고 다음 규칙을 추가합니다.

      • 수신:

        보안 목록 수신 규칙

      • 송신:

        보안 목록 송신 규칙

  6. 로드 밸런서로부터의 접속을 허용하도록 워커 노드 서브넷과 연관된 보안 목록을 업데이트합니다.

    1. VCN 이름을 누릅니다.

      OKE 클러스터 VCN

    2. Resources 아래에서 Security Lists를 선택하고 노드 보안 목록을 누릅니다.

      보안 목록

    3. 노드 보안 목록에 다음 수신 규칙을 추가합니다.

      노드 보안 목록 수신

    4. 수신 규칙 추가를 누릅니다.

작업 2: Nginx 수신 컨트롤러 설정

  1. 클러스터를 사용할 수 있게 되면 OCI Cloud Shell을 사용하여 클러스터에 액세스할 수 있습니다. 클러스터 액세스를 누르고 OCI Cloud Shell에서 다음 명령을 복사하여 실행합니다.

    클러스터에 액세스

  2. kubectl get node 명령을 실행하여 사용 가능한 노드 목록을 가져옵니다.

    노드 가져오기

  3. Nginx Ingress Controller Helm 저장소를 추가합니다. 자세한 내용은 Overview of Ingress NGINX Controllerhelm를 참조하십시오.

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    
  4. 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"
    
  5. Nginx 수신 컨트롤러를 배치합니다.

    helm install ingress-nginx ingress-nginx/ingress-nginx -f values-override.yaml
    
  6. 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"
    
  7. 응용 프로그램 리소스를 만듭니다.

    kubectl apply -f application.yaml
    
  8. 로드 밸런서와 연관된 공용 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를 사용합니다.

    이 경우 FQDN158-180-61-74.nip.io입니다.

  9. 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
    
  10. 다음 명령을 실행하여 수신 리소스를 만듭니다.

    kubectl apply -f ingress.yaml
    
  11. 서비스에 대한 접속을 테스트합니다.

    $ 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에서 기밀 애플리케이션 설정

  1. OCI 콘솔에서 Oracle Identity Domains로 이동하고 OracleIdentityCloudService 도메인을 누릅니다.

  2. 왼쪽 메뉴에서 통합 애플리케이션을 선택하고 애플리케이션 추가를 누릅니다.

  3. 기밀 애플리케이션을 선택하고 워크플로우 실행을 누릅니다.

    새 기밀 애플리케이션

  4. 애플리케이션 이름, 설명을 입력하고 다음을 누릅니다.

    애플리케이션 세부정보

  5. 애플리케이션 oAuth 매개변수를 구성합니다.

    1. 권한 부여 섹션에서 권한 부여 코드를 선택합니다.

    2. 다음 URL을 입력하고 다음을 누릅니다.

      • 재지정 URL: https://<YOUR-FQDN>/oauth2/callback.
      • 사후 로그아웃 재지정 URL: https://<YOUR-FQDN>.
      • 로그아웃 URL: https://<YOUR-FQDN>/oauth2/sign_out.

    애플리케이션 OAuth 파라미터

  6. 웹 계층 정책에서 건너뛰기 후 나중에 수행을 선택하고 완료를 누릅니다.

    웹 계층 정책

  7. 활성화를 눌러 애플리케이션을 사용으로 설정합니다.

    애플리케이션 활성화

  8. 왼쪽 메뉴에서 그룹으로 이동하여 이 애플리케이션에 인증할 수 있는 사용자 그룹을 연관시킵니다.

    응용 프로그램과 사용자 그룹 연관

  9. 고객 ID고객 암호를 적어둡니다.

    애플리케이션 클라이언트 ID 및 암호

  10. OracleIdentityCloudService 도메인을 누르고 도메인 URL을 확장합니다.

    ID 도메인 URL

    예: ID 도메인 URLhttps://idcs-01234567890abcdef.identity.oraclecloud.com입니다(포트 번호 제거).

작업 4: OAuth2 프록시 배치

OAuth2 프록시를 사용하여 OAuth2 또는 OIDC(OpenID Connect) 복잡성을 처리하고 애플리케이션으로 전달된 모든 요청이 인증되었는지 확인합니다.

  1. 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>
    
  2. OKE에 OAuth2 프록시를 배치합니다.

    kubectl apply -f oauth2-proxy.yaml
    

    Pod가 실행 중인지 확인합니다.

    kubectl get pods -l k8s-app=oauth2-proxy
    
  3. 요청 인증에 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
    
  4. 응용 프로그램에 연결해 봅니다. Oracle 인증 페이지로 재지정되어야 합니다. 인증이 성공하면 애플리케이션으로 재지정되어야 합니다.

    인증 페이지

    인증된 사용자를 식별하는 두 개의 헤더가 있습니다.

    "x-auth-request-user": "xxxx@oracle.com"
    "x-auth-request-email": "xxxx@oracle.com"
    
  5. 애플리케이션에서 사인아웃하려면 페이지의 /oauth2/sign_out으로 이동할 수 있습니다.

    https://<YOUR-FQDN>/oauth2/sign_out
    

    알려진 문제: 사후 사인아웃 재지정이 작동하지 않습니다. 이 문제는 OIDC 제공자에 대한 로그아웃 제공자 URL에 id_token_hint 매개변수 추가에서 추적됩니다.

작업 5: 리소스 정리

  1. 다음 명령을 실행하여 모든 Kubernetes 배치된 리소스를 삭제합니다.

    kubectl delete -f oauth2-proxy.yaml -f ingress.yaml -f application.yaml
    helm uninstall ingress-nginx
    
  2. Oracle Identity Domains에서 응용 프로그램을 삭제합니다.

  3. OKE 클러스터를 삭제합니다.

  4. OKE 클러스터에 대해 생성된 VCN을 삭제합니다.

    참고:

    • OKE 클러스터 및 노드 풀 삭제가 종료될 때까지 기다려야 합니다.

    • VCN 이름에는 OKE 클러스터의 이름이 포함됩니다. oke-vcn-quick-<oke-cluster-name>-<random-string>.

확인

추가 학습 자원

docs.oracle.com/learn에서 다른 실습을 살펴보거나 Oracle Learning YouTube 채널에서 더 많은 무료 학습 콘텐츠에 액세스하십시오. 또한 education.oracle.com/learning-explorer를 방문하여 Oracle Learning Explorer가 되십시오.

제품 설명서는 Oracle Help Center를 참조하십시오.