클러스터 메타데이터 보호

개요

GKE는 인스턴스 메타데이터를 사용하여 노드 VM을 구성하지만, 이 메타데이터 중 일부는 잠재적으로 민감한 데이터를 포함하며, 클러스터에서 실행되는 워크로드로부터 보호되어야 합니다.

시작하기 전에

시작하기 전에 다음 태스크를 수행했는지 확인합니다.

다음 방법 중 하나를 사용하여 기본 gcloud 설정을 진행합니다.

  • gcloud init를 사용하여 기본값 설정 과정을 진행합니다.
  • gcloud config를 사용하여 프로젝트 ID, 영역, 리전을 개별적으로 설정합니다.

gcloud init 사용

One of [--zone, --region] must be supplied: Please specify location 오류가 표시되면 이 섹션을 완료합니다.

  1. gcloud init를 실행하고 다음 안내를 따르세요.

    gcloud init

    원격 서버에서 SSH를 사용하는 경우 --console-only 플래그를 사용하여 다음 명령어로 브라우저를 실행하지 못하게 할 수 있습니다.

    gcloud init --console-only
  2. 안내를 따라 gcloud에서 Google Cloud 계정을 사용하도록 승인합니다.
  3. 새 구성을 만들거나 기존 구성을 선택합니다.
  4. Google Cloud 프로젝트를 선택합니다.
  5. 기본 Compute Engine 영역을 선택합니다.

gcloud config 사용

  • 기본 프로젝트 ID를 설정합니다.
    gcloud config set project project-id
  • 영역 클러스터를 사용하는 경우 기본 컴퓨팅 영역을 설정합니다.
    gcloud config set compute/zone compute-zone
  • 리전 클러스터를 사용하는 경우 기본 컴퓨팅 리전을 설정합니다.
    gcloud config set compute/region compute-region
  • gcloud를 최신 버전으로 업데이트합니다.
    gcloud components update

노드 서비스 계정 구성

각 노드의 서비스 계정 사용자 인증 정보가 워크로드에 계속 노출되기 때문에, 필요한 최소 권한으로 서비스 계정을 구성했는지 확인해야 합니다. 그런 후 서비스 계정을 노드에 연결하여, 공격자가 Compute Engine API를 사용해서 노드 인스턴스에 직접 액세스하여 GKE의 메타데이터 보호를 우회할 수 없도록 해야 합니다.

compute.instances.get 권한, 컴퓨팅 인스턴스 관리자 역할 또는 기타 유사한 권한이 있는 서비스 계정은 사용하지 마세요. 그렇지 않으면 공격자가 Compute Engine API를 사용하여 인스턴스 메타데이터를 획득할 수 있습니다. 권장사항은 액세스 범위가 아니라 서비스 계정 권한을 사용하여 노드 VM의 권한을 제한하는 것입니다. 자세한 내용은 Compute Engine의 서비스 계정 문서를 참조하세요.

노드 서비스 계정이 없으면 다음 명령어를 사용하여 만들 수 있습니다.

export NODE_SA_NAME=gke-node-sa
gcloud iam service-accounts create $NODE_SA_NAME \
  --display-name "Node Service Account"
export NODE_SA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \
  --filter='displayName:Node Service Account')

필요한 역할 및 권한으로 서비스 계정을 구성하려면 다음 명령어를 실행하세요. PROJECT프로젝트 ID입니다.

export PROJECT=$(gcloud config get-value project)

gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/monitoring.metricWriter
gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/monitoring.viewer
gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/logging.logWriter

또한 클러스터가 Container Registry에서 비공개 이미지를 가져오는 경우 storage.objectViewer 역할을 추가합니다.

gcloud projects add-iam-policy-binding $PROJECT \
  --member serviceAccount:$NODE_SA_EMAIL \
  --role roles/storage.objectViewer

기존 메타데이터 API 사용 중지 및 전환

Compute Engine v1beta1 서버와 v0.1 메타데이터 서버 엔드포인트는 지원 중단되었으며 서비스가 종료될 예정입니다. v1 엔드포인트를 사용하도록 모든 요청을 업데이트해야 합니다.

Compute Engine 인스턴스 메타데이터 서버는 메타데이터 쿼리 헤더를 적용하지 않는 기존 v0.1 및 v1beta1 엔드포인트를 노출합니다. 이 기능은 잠재적인 공격자가 인스턴스 메타데이터를 검색하기 어렵게 만드는 v1 API의 기능입니다. 특별히 필요하지 않다면 이러한 이전 API를 사용 중지하는 것이 좋습니다.

다음 섹션에서는 다음 작업을 수행하는 방법을 설명합니다.

  • 지원 중단된 엔드포인트에 액세스하는 노드가 어느 것인지 식별합니다. 노드에서 지원 중단된 엔드포인트를 사용하는 경우 이 노드를 마이그레이션해야 합니다.

  • 이 식별된 노드에 대한 기존 메타데이터 서버 엔드포인트의 사용을 중지한 상태로 새로운 클러스터 또는 노드 풀을 만듭니다.

기존 메타데이터 서버 엔드포인트를 사용하여 노드 식별

check-legacy-endpoint-access 도구를 사용하여 기존 메타데이터 서버 엔드포인트를 사용 중인 Kubernetes Engine 노드를 확인할 수 있습니다. 이 도구는 클러스터에 적용될 때 5분마다 노드에서 v0.1 및 v1beta1 엔드포인트에 대한 모든 요청을 기록합니다. 이 도구를 사용하면 Kubernetes Engine에서 기존 엔드포인트 사용을 식별, 디버깅, 확인할 수도 있습니다.

check-legacy-endpoint-access 도구를 설정하려면 다음 단계를 완료하세요.

  1. 각 클러스터에서 다음 명령어를 실행합니다.

    kubectl apply -f \
    https://raw.githubusercontent.com/GoogleCloudPlatform\
    /k8s-node-tools/master/check-legacy-endpoint-access/check-legacy-endpoint-access.yaml
  2. 기존 엔드포인트 사용량 정보로 수집된 로그를 쿼리합니다. 로그를 쿼리하려면 각 클러스터에서 다음 명령어를 실행합니다.

    kubectl -n kube-system logs -l \
    app=check-legacy-endpoint-access | grep "access count"

Stackdriver Logging에서 수집된 로그를 볼 수도 있습니다.

  1. Cloud Console에서 Cloud Logging > 로그(로그 뷰어) 페이지로 이동합니다.

    로그 뷰어 페이지로 이동

  2. 다음 필터를 적용합니다.

    resource.type="container"
    resource.labels.namespace_id="kube-system"
    logName:"/check-legacy-endpoint-access"

    필터링 뷰로 이동

  3. 노드를 식별한 후에는 이러한 엔드포인트를 사용 중인 프로세스를 식별해야 합니다. 이러한 프로세스 식별에 대한 자세한 내용은 프로세스 식별을 참조하세요.

  4. 이러한 프로세스를 마이그레이션해 v1 메타데이터 서버 엔드포인트를 사용합니다. Compute Engine 노드의 마이그레이션 안내와 엔드포인트 차이점에 대한 자세한 내용은 v1 메타데이터 서버 엔드포인트로 마이그레이션을 참조하세요.

  5. check-legacy-endpoint-access daemonset를 삭제합니다.

    kubectl delete daemonset check-legacy-endpoint-access -n kube-system

이전 메타데이터 API가 사용 중지된 상태로 새 노드 풀 만들기

서비스 계정을 만든 후 gcloud 명령줄 도구를 사용하여 기존 메타데이터 API의 사용이 중지된 새 노드 풀(또는 새 클러스터의 기본 노드 풀)을 만들 수 있습니다.

기존 메타데이터 API의 사용이 중지된 새 노드 풀을 만들려면 --metadata disable-legacy-endpoints=true 플래그를 사용합니다. 예를 들면 다음과 같습니다.

gcloud container node-pools create pool-name \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

동일한 플래그를 사용해서 기본 노드 풀에 이전 메타데이터 API가 사용 중지된 상태로 새 클러스터를 만들 수 있습니다. 예를 들면 다음과 같습니다.

gcloud container clusters create cluster-name \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true

기존 메타데이터 API를 사용 중지하도록 기존 클러스터 업데이트

기존 메타데이터 API의 사용이 중지된 상태로 새 노드 풀을 만든 후에는 노드 풀 이전 가이드에 따라 이를 사용하도록 기존 클러스터를 업데이트할 수 있습니다.

기존 메타데이터 API의 사용이 중지되었는지 확인

기존 인스턴스 메타데이터 API의 사용이 중지되면 /0.1//v1beta1/ 메타데이터 서버 엔드포인트에 대한 요청이 403 Forbidden을 반환합니다.

기존 메타데이터 API의 사용이 중지되었는지 확인하려면 pod 내에서 curl 명령어를 실행할 수 있습니다.

root@pod-name# curl -H 'Metadata-Flavor: Google' \
'http://metadata.google.internal/computeMetadata/v1/instance/attributes/disable-legacy-endpoints'
true
root@pod-name# curl 'http://metadata.google.internal/computeMetadata/v1beta1/instance/id'
... Error 403 (Forbidden) ... Legacy metadata endpoint accessed: /computeMetadata/v1beta1/instance/id Legacy metadata endpoints are disabled. Please use the /v1/ endpoint. ...

메타데이터 숨김

GKE의 메타데이터 숨김은 클러스터에서 실행되는 사용자 워크로드에서 잠재적으로 민감한 시스템 메타데이터를 보호합니다.

Kubernetes v1.9.3 이상에서는 메타데이터 숨김을 사용 설정하여 사용자 Pod가 Kubelet 사용자 인증 정보 및 VM 인스턴스 정보와 같은 클러스터 노드에 대한 특정 VM 메타데이터에 액세스하는 것을 방지할 수 있습니다. 특히 메타데이터 숨김은 Kubelet 사용자 인증 정보를 포함하는 kube-env 및 VM의 인스턴스 ID 토큰에 대한 액세스를 보호합니다.

메타데이터 숨김은 사용자 pod(HostNetwork에서 실행되지 않는 pod)에서 클러스터 메타데이터 서버로 보내는 트래픽에 방화벽을 적용하여 안전한 쿼리만 허용합니다. 이 방화벽은 사용자 pod의 권한 에스컬레이션 공격을 위한 Kubelet 사용자 인증 정보 사용 또는 인스턴스 승격 공격을 위한 VM ID 사용을 방해합니다.

제한사항

  • 메타데이터 숨김은 kube-env 및 노드의 인스턴스 ID 토큰에 대한 액세스만 보호합니다.
  • 메타데이터 숨김은 노드의 서비스 계정에 대한 액세스를 제한하지 않습니다.
  • 메타데이터 숨김은 다른 관련 인스턴스 메타데이터에 대한 액세스를 제한하지 않습니다.
  • 메타데이터 숨김은 다른 이전 메타데이터 API에 대한 액세스를 제한하지 않습니다.

메타데이터 숨김으로 새 클러스터 또는 노드 풀 만들기

서비스 계정을 만든 후 gcloud 명령줄 도구를 사용하여 메타데이터 숨김이 사용 설정된 상태로 새 클러스터를 만들 수 있습니다.

메타데이터 숨김이 사용 설정된 상태로 클러스터를 만들려면 셸 또는 터미널 창에서 다음 명령어를 실행합니다.

gcloud beta container clusters create cluster-name \
  --workload-metadata-from-node=SECURE \
  --service-account=$NODE_SA_EMAIL \
  --metadata disable-legacy-endpoints=true \
  [additional parameters and flags omitted]

각 항목의 의미는 다음과 같습니다.

  • cluster-name은 생성할 클러스터의 이름입니다.
  • --workload-metadata-from-nodeSECURE로 설정됩니다. 플래그를 EXPOSED 또는 UNSPECIFIED로 설정하면 메타데이터 숨김이 중지됩니다.

클러스터 워크로드에서 숨겨진 ID 토큰 메타데이터 확인

메타데이터를 숨기면 노드의 인스턴스 ID 토큰을 통해 서명을 요청할 수 없어야 합니다. 해당 요청이 숨겨진 메타데이터를 사용자에게 명시적으로 알리는지 확인하려면 Pod 내에서 curl 명령어를 실행하면 됩니다.

root@pod-name# curl -H "Metadata-Flavor: Google" \
'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://www.example.com'
This metadata endpoint is concealed.