Istio 및 Identity Platform을 사용하여 Cloud Run for Anthos 서비스 최종 사용자 인증

이 가이드에서는 Istio 인증 정책Identity Platform을 사용하여 Cloud Run for Anthos on Google Cloud에 배포된 애플리케이션의 최종 사용자를 인증하는 방법을 보여줍니다. 인증을 위해 Istio를 사용하면 인증 로직이 애플리케이션 코드에 속할 필요가 없습니다. 이렇게 분리하면 서로 다른 팀에서 애플리케이션 코드 및 인증 정책을 담당하고 인증 정책을 여러 애플리케이션 또는 서비스 전반에 적용할 수 있습니다.

소개

Cloud Run for Anthos는 GKE에서 실행되는 애플리케이션 및 기능을 배포하고 제공하는 개발자 중심 환경을 제공합니다. 이는 개발팀에 서버리스 환경을 제공하여 수요에 따른 자동 확장, 블루-그린 배포를 위한 라우팅 및 트래픽 관리 등을 지원합니다. Cloud Run for Anthos는 오픈소스 프로젝트 Istio 및 Knative 위에 빌드되며, Cloud Logging과 같은 Google Cloud 제품들과 통합됩니다.

Istio는 인증 정책에 따라 JWT(JSON 웹 토큰)를 검증하여 수신 요청을 인증할 수 있습니다. 인증 정책은 네임스페이스의 모든 서비스 또는 특정 이름의 서비스에 적용될 수 있습니다. 정책은 예를 들어 공개 웹사이트 애셋 및 상태 확인 엔드포인트에 대한 비인증 액세스를 허용하기 위해 특정 HTTP 요청 경로를 포함하거나 제외할 수 있습니다. 이 가이드에서는 Istio 인그레스 게이트웨이가 인증 정책을 시행합니다.

다음 다이어그램은 이 가이드의 토대가 되는 인증 흐름을 보여줍니다.

Istio의 수신 요청 인증

이 가이드에서는 Identity Platform을 사용하여 최종 사용자의 로그인을 지원하지만, OpenID Connect를 지원하는 다른 공급업체(예: Google 로그인, Firebase 인증), 타사 서비스(예: Auth0, Gluu, Okta, Ping Identity), OpenID Connect 구현의 직접 배포에 맞게 솔루션을 조정할 수 있습니다.

목표

  • Cloud Run 부가기능으로 GKE 클러스터 만들기
  • Identity Platform 설정
  • 공개 프런트엔드 및 백엔드 API로 구성되는 샘플 애플리케이션 배포
  • 백엔드 API에 대한 인증 정책 추가
  • 인증 확인

비용

이 가이드에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 가이드를 마치면 만든 리소스를 삭제하여 비용이 계속 청구되지 않게 할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

  1. Google 계정에 로그인하거나 Google 계정이 없으면 새 계정에 가입합니다.
  2. Google Cloud Console에서 프로젝트 선택기 페이지로 이동합니다.

    프로젝트 선택기로 이동

  3. Google Cloud 프로젝트를 선택하거나 만듭니다.

  4. Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다. 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.

  5. Cloud Build, Cloud Run, 컨테이너 분석, Google Kubernetes Engine API, Cloud APIs를 사용 설정합니다.

    API 사용 설정

환경 초기화

이 섹션에서는 가이드 뒷부분에서 사용할 환경 변수 및 gcloud 기본값을 설정합니다.

  1. Cloud Console의 프로젝트 선택 드롭다운에서 사용할 프로젝트를 선택합니다.

  2. Cloud Shell을 엽니다.

    Cloud Shell로 이동

    Cloud Shell을 사용하여 가이드의 모든 명령어를 실행합니다.

  3. 이 가이드에서 사용할 Compute Engine 영역 및 GKE 클러스터 이름의 환경 변수 및 gcloud 기본값을 정의합니다.

    ZONE=us-central1-c
    CLUSTER=cloud-run-gke-auth-tutorial
    
    gcloud config set compute/zone $ZONE
    gcloud config set run/cluster $CLUSTER
    gcloud config set run/cluster_location $ZONE
    

    필요에 맞게 영역 및 클러스터 이름을 변경할 수 있습니다.

Cloud Run이 사용 설정된 GKE 클러스터 만들기

  • Cloud Run 부가기능으로 GKE 클러스터를 만듭니다.

    gcloud beta container clusters create $CLUSTER \
        --addons HorizontalPodAutoscaling,HttpLoadBalancing,CloudRun \
        --enable-ip-alias \
        --enable-stackdriver-kubernetes \
        --machine-type n1-standard-2
    

공개 IP 주소 찾기

Cloud Run for Anthos on Google Cloud는 외부 서비스를 Istio 인그레스 게이트웨이의 공개 IP 주소로 노출시킵니다.

  1. istio-ingress Kubernetes 서비스용 외부 IP 주소 생성 상태를 확인합니다.

    kubectl get services istio-ingress -n gke-system --watch
    

    EXTERNAL-IP 값이 <pending>에서 IP 주소로 변경될 때까지 기다립니다. NotFound 오류가 발생하면 1분 동안 기다렸다가 명령어를 다시 실행합니다. 대기를 중단하려면 Control+C를 누릅니다.

  2. Istio 인그레스 게이트웨이의 공개 IP 주소를 저장할 환경 변수를 만듭니다.

    export EXTERNAL_IP=$(kubectl get services istio-ingress \
        --namespace gke-system \
        --output jsonpath='{.status.loadBalancer.ingress[0].ip}')
    
  3. Istio 인그레스 게이트웨이의 공개 IP 주소를 표시합니다. 이후에 이 주소가 필요합니다.

    echo $EXTERNAL_IP
    

참고: 이 가이드에서는 IP 주소와 암호화되지 않은 HTTP를 사용하여 서비스에 액세스합니다. 프로덕션 설정 시에는 다음을 모두 수행하는 것이 좋습니다.

Identity Platform 설정

  1. Cloud Shell을 열어 두고 Google Cloud Marketplace를 방문하여 새 웹브라우저 창에서 Identity Platform을 사용 설정합니다.

    Google Cloud Marketplace에서 Identity Platform으로 이동

  2. 프로젝트 선택 드롭다운에서 Identity Platform을 설정하려는 Google Cloud 프로젝트를 선택합니다. GKE 클러스터 및 Identity Platform을 개별 Google Cloud 프로젝트에 설정할 수 있습니다. 간단하게 진행할 수 있도록 이 가이드에서는 동일한 프로젝트를 사용합니다.

  3. Identity Platform 사용 설정을 클릭합니다.

    현재 위치는 Cloud Console에서 Identity Platform > 공급업체 페이지입니다.

  4. 공급업체 페이지에서 공급업체 추가를 클릭합니다.

  5. 공급업체 선택 드롭다운에서 아래로 스크롤하여 이메일/비밀번호를 선택합니다. 자체 애플리케이션의 경우 사용 설정할 공급업체를 선택할 수 있습니다.

  6. 사용 설정됨이 선택되었는지 확인합니다.

  7. 비밀번호 없는 로그인 허용을 선택 해제합니다.

  8. 저장을 클릭합니다.

  9. Identity Platform > 설정 페이지로 이동합니다.

  10. 보안 탭을 클릭합니다.

  11. 도메인 추가를 클릭합니다. 승인된 도메인 추가 대화상자가 열립니다.

  12. 도메인 상자에 이전 섹션에서 찾은 Istio 인그레스 게이트웨이의 공개 IP 주소($EXTERNAL_IP)를 입력합니다.

  13. 추가를 클릭합니다. 대화상자가 닫힙니다. 입력한 IP 주소는 승인된 도메인 테이블에 있습니다.

  14. Identity Platform > 설정 페이지에서 저장을 클릭합니다.

테스트 사용자 만들기

  1. Cloud Console에서 Identity Platform > 사용자 페이지로 이동합니다.
  2. 사용자 추가를 클릭하여 이 가이드의 테스트 사용자를 추가합니다. 사용자 추가 대화상자가 열립니다.
  3. 이메일 상자에 최종 사용자의 이메일 주소를 입력합니다. 테스트를 위해서는 실제 이메일 주소를 사용할 필요가 없습니다. 이 가이드에서는 user@example.com을 사용합니다.
  4. 비밀번호 상자에 테스트 사용자의 비밀번호를 입력합니다. 나중에 필요하므로 이 암호를 기억해 둡니다.
  5. 추가를 클릭하여 사용자 추가를 마칩니다. 대화상자가 닫히고 Identity Platform > 사용자 페이지로 돌아갑니다.

샘플 애플리케이션 만들기

두 개의 서비스가 있는 샘플 애플리케이션을 배포합니다. 한 서비스는 공개 프런트엔드 사용자 인터페이스이고, 다른 서비스는 백엔드 API입니다.

  1. Identity Platform > 사용자 페이지에서 창의 오른쪽에 있는 애플리케이션 설정 세부정보 링크를 클릭합니다. 애플리케이션 구성 대화상자가 열립니다.

  2. apiKey의 값을 강조표시하고 클립보드에 복사합니다(Chrome OS/Linux/Windows의 경우 Control+C, macOS의 경우 Cmd+C).

  3. 닫기를 클릭하여 애플리케이션 구성 대화상자를 닫습니다.

  4. Cloud Shell에서 환경 변수를 만들어 apiKey를 저장합니다. 여기서 api-key애플리케이션 구성 대화상자에 있었던 apiKey입니다.

    export AUTH_APIKEY=api-key
    
  5. authDomain의 환경 변수를 만듭니다.

    export AUTH_DOMAIN=$GOOGLE_CLOUD_PROJECT.firebaseapp.com
    
  6. GitHub의 Cloud Run 샘플 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples.git
    
  7. 이 가이드의 파일이 있는 디렉터리로 전환합니다.

    cd cloud-run-samples/identity-platform/gke
    
  8. 프런트엔드 JavaScript 파일에서 Identity Platform 변수를 바꿉니다.

    envsubst < frontend/index.template.js > frontend/index.js
    

샘플 애플리케이션 배포

  1. Cloud Build를 사용하여 샘플 애플리케이션의 컨테이너 이미지를 2개 만듭니다. 1개는 프런트엔드용이고 다른 하나는 백엔드용입니다.

    gcloud builds submit -t gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-frontend frontend
    
    gcloud builds submit -t gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-backend backend
    

    Cloud Build는 Container Registry에 이미지를 저장합니다.

  2. GKE 클러스터에서 publicapi라는 네임스페이스를 2개 만듭니다.

    kubectl create namespace public
    
    kubectl create namespace api
    
  3. Google Cloud에서 프런트엔드 컨테이너 이미지를 public 네임스페이스의 서비스로 Cloud Run for Anthos에 배포합니다.

    gcloud run deploy frontend \
        --namespace public \
        --image gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-frontend \
        --platform gke
    
  4. Google Cloud에서 백엔드 컨테이너 이미지를 api 네임스페이스의 서비스로 Cloud Run for Anthos에 배포합니다.

    gcloud run deploy backend \
        --namespace api \
        --image gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-backend \
        --platform gke
    
  5. URI 경로로 요청을 라우팅하는 Istio 가상 서비스를 만듭니다.

    kubectl apply -f istio/virtualservice.yaml
    

    이 가상 서비스는 URI 경로가 /api/로 시작되는 요청은 백엔드 API로 라우팅하고 기타 모든 요청은 프런트엔드 사용자 인터페이스로 라우팅합니다.

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: cloud-run-gke-auth
    spec:
      gateways:
      - gke-system-gateway.knative-serving.svc.cluster.local
      hosts:
      - "*"
      http:
      - match:
        - uri:
            prefix: "/api/"
        rewrite:
          authority: backend.api.svc.cluster.local
        route:
        - destination:
            host: cluster-local-gateway.gke-system.svc.cluster.local
      - match:
        - uri:
            prefix: "/"
        rewrite:
          authority: frontend.public.svc.cluster.local
        route:
        - destination:
            host: cluster-local-gateway.gke-system.svc.cluster.local
  6. 백엔드 API에 대한 비인증 요청이 성공했는지 확인합니다.

    curl -si $EXTERNAL_IP/api/secure.json | head -n1
    

    HTTP/1.1 200 OK가 출력되지 않은 경우 1분 동안 기다린 후 다시 시도하세요.

Istio 인증 정책 추가

  1. Istio 인증 정책을 만듭니다.

    envsubst < istio/authenticationpolicy.template.yaml | kubectl apply -f -
    
    apiVersion: authentication.istio.io/v1alpha1
    kind: Policy
    metadata:
      name: api-origin-auth
      namespace: gke-system
    spec:
      targets:
      - name: istio-ingress
        ports:
        - number: 80
        - number: 443
      origins:
      - jwt:
          issuer: "https://securetoken.google.com/$GOOGLE_CLOUD_PROJECT"
          audiences:
          - "$GOOGLE_CLOUD_PROJECT"
          jwksUri: "https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"
          trigger_rules:
          - excluded_paths:
            - exact: /api/healthz
            included_paths:
            - prefix: /api/
      principalBinding: USE_ORIGIN

    이 정책은 URI 경로가 /api/로 시작되는 요청(/api/healthz 경로 제외)을 인증합니다. 이전 섹션에서 배포된 Istio 가상 서비스의 라우팅 규칙으로 인해 이 정책은 백엔드 API에 대한 요청을 인증합니다.

  2. 정책이 적용되는 데 다소 시간이 걸릴 수 있습니다. 다음 명령어를 실행하고 HTTP/1.1 401 Unauthorized가 Console에 출력될 때까지 기다립니다.

    while sleep 2; do
      curl -si $EXTERNAL_IP/api/secure.json | head -n1
    done
    

    처음에는 HTTP/1.1 200 OKHTTP/1.1 401 Unauthorized가 번갈아 출력될 수 있습니다. 이는 IstioEnvoy 프록시의 eventual consistency 때문입니다.

    Console에 HTTP/1.1 401 Unauthorized만 출력되면 Control+C를 눌러 대기를 중지합니다.

솔루션 테스트

  1. http://$EXTERNAL_IP/api/secure.json 주소로 브라우저 창을 엽니다. 여기에서 $EXTERNAL_IP공개 IP 주소 찾기 섹션에서 찾은 Istio 인그레스 게이트웨이의 공개 IP 주소입니다.

    이는 백엔드 API에 대한 직접 요청입니다. 요청에 Istio 인증 정책을 충족하는 사용자 인증 정보가 포함되어 있지 않으므로 브라우저 창에 Origin authentication failed(원본 인증 실패)가 표시됩니다.

  2. $EXTERNAL_IP 주소로 브라우저 창을 엽니다. 로그인 양식이 표시됩니다.

  3. 테스트 사용자 만들기 섹션에서 만든 테스트 사용자로 로그인합니다.

    페이지에 테스트 사용자 이메일 주소와 The secret message is: Hello World(보안 비밀 메시지는 Hello World입니다) 텍스트가 표시됩니다. 메시지가 표시되는 데 다소 시간이 걸릴 수 있습니다.

    브라우저는 로그인할 때 Identity Platform에서 획득한 토큰을 사용하여 백엔드 API에 대한 HTTP 요청(/api/secure.json)에 따라 메시지를 가져옵니다. frontend/index.js 파일을 검사하여 구현을 확인하고 FirebaseUI 라이브러리에서 추가 문서를 참조합니다.

문제해결

이 가이드에서 문제가 발생하면 다음 문서를 검토하시기 바랍니다.

삭제

이 가이드에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 안내를 따르세요.

  1. Cloud Console에서 리소스 관리 페이지로 이동합니다.

    리소스 관리로 이동

  2. 프로젝트 목록에서 삭제할 프로젝트를 선택하고 삭제를 클릭합니다.
  3. 대화상자에서 프로젝트 ID를 입력한 후 종료를 클릭하여 프로젝트를 삭제합니다.

리소스 삭제

이 가이드에서 사용된 Google Cloud 프로젝트를 유지하려면 개별 리소스를 삭제합니다.

  1. GKE 클러스터를 삭제합니다.

    gcloud container clusters delete $CLUSTER --async --quiet
    
  2. Container Registry에서 샘플 애플리케이션 컨테이너 이미지를 삭제합니다.

    gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-frontend \
        --force-delete-tags --quiet
    
    gcloud container images delete gcr.io/$GOOGLE_CLOUD_PROJECT/cloud-run-gke-auth-backend \
        --force-delete-tags --quiet
    
  3. Identity Platform에서 이메일/비밀번호 ID 공급업체를 삭제합니다.

    1. Cloud Console에서 Identity Platform > 공급업체 페이지로 이동합니다.

      공급업체 페이지로 이동

    2. 공급업체 테이블에서 이메일/비밀번호 ID 공급업체를 찾아 를 클릭합니다.

    3. 표시되는 대화상자에서 삭제를 클릭하여 확인합니다.

  4. 테스트 사용자를 삭제합니다.

    1. Identity Platform > 사용자 페이지로 이동합니다.

      사용자 페이지로 이동

    2. 사용자 테이블에서 user@example.com을 찾아 를 클릭합니다.

    3. 표시되는 대화상자에서 삭제를 클릭하여 확인합니다.

  5. 승인된 도메인을 삭제합니다.

    1. Identity Platform > 설정 페이지로 이동합니다.

      설정 페이지로 이동

    2. 승인된 도메인 테이블에서 Identity Platform 설정 섹션에서 추가한 IP 주소($EXTERNAL_IP)를 찾아 를 클릭합니다.

    3. 저장을 클릭합니다.

다음 단계