실습 설정 안내 및 요구사항
계정과 진행 상황을 보호하세요. 이 실습을 실행하려면 항상 시크릿 브라우저 창과 실습 사용자 인증 정보를 사용하세요.

기본 GKE 클러스터 구성 강화

실습 25분 universal_currency_alt 크레딧 7개 show_chart 고급
info 이 실습에는 학습을 지원하는 AI 도구가 통합되어 있을 수 있습니다.
이 콘텐츠는 아직 휴대기기에 최적화되지 않음
최상의 경험을 위해 데스크톱 컴퓨터에서 이메일로 전송된 링크를 사용하여 방문하세요.

GSP496

Google Cloud 사용자 주도형 실습 로고

개요

이 실습에서는 기본 GKE 클러스터 구성에서 발생할 수 있는 몇 가지 보안 우려 사항과 포드 이스케이프 및 클러스터 권한 에스컬레이션으로 이어질 수 있는 여러 공격 경로를 방지하기 위한 대응 보안 강화 조치를 살펴봅니다. 이러한 공격 경로는 다음과 같은 시나리오에서 특히 문제가 됩니다.

  1. 외부에 노출된 포드에서 서버 측 요청 위조(SSRF) 공격을 가능하게 하는 애플리케이션 취약점이 존재하는 경우
  2. 포드 내부의 컨테이너가 완전히 장악되어 원격 명령어 실행(RCE)이 가능한 경우
  3. 특정 네임스페이스에서 포드를 생성/업데이트할 수 있는 권한을 가진 악의적인 내부 사용자 또는 내부 사용자 인증 정보를 탈취한 공격자

이 실습은 기본 GKE 클러스터 구성 강화에 대한 이해를 돕기 위해 GKE Helmsman 엔지니어가 제작했습니다.

이 실습의 예시 코드는 보증이나 보장 없이 있는 그대로 제공됩니다.

목표

이 실습을 완료하면 GKE 인스턴스 메타데이터를 보호해야 하는 필요성과, 환경에 적합한 PodSecurityPolicy 정책을 정의해야 하는 이유를 이해하게 됩니다.

실습할 내용은 다음과 같습니다.

  1. 기본 설정을 사용하여 소규모 GKE 클러스터를 만듭니다.
  2. 악의적인 내부 사용자 관점에서 포드 이스케이프 및 클러스터 권한 에스컬레이션으로 이어지는 가장 흔한 공격 경로를 검증합니다.
  3. 이러한 문제를 해결하기 위해 GKE 클러스터를 강화합니다.
  4. 이러한 작업이 더 이상 허용되지 않도록 클러스터를 검증합니다.

설정 및 요건

실습 시작 버튼을 클릭하기 전에

다음 안내를 확인하세요. 실습에는 시간 제한이 있으며 일시중지할 수 없습니다. 실습 시작을 클릭하면 타이머가 시작됩니다. 이 타이머는 Google Cloud 리소스를 사용할 수 있는 시간이 얼마나 남았는지를 표시합니다.

실무형 실습을 통해 시뮬레이션이나 데모 환경이 아닌 실제 클라우드 환경에서 실습 활동을 진행할 수 있습니다. 실습 시간 동안 Google Cloud에 로그인하고 액세스하는 데 사용할 수 있는 새로운 임시 사용자 인증 정보가 제공됩니다.

이 실습을 완료하려면 다음을 준비해야 합니다.

  • 표준 인터넷 브라우저 액세스 권한(Chrome 브라우저 권장)
참고: 이 실습을 실행하려면 시크릿 모드(권장) 또는 시크릿 브라우저 창을 사용하세요. 개인 계정과 학습자 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.
  • 실습을 완료하기에 충분한 시간(실습을 시작하고 나면 일시중지할 수 없음)
참고: 이 실습에는 학습자 계정만 사용하세요. 다른 Google Cloud 계정을 사용하는 경우 해당 계정에 비용이 청구될 수 있습니다.

실습을 시작하고 Google Cloud 콘솔에 로그인하는 방법

  1. 실습 시작 버튼을 클릭합니다. 실습 비용을 결제해야 하는 경우 결제 수단을 선택할 수 있는 대화상자가 열립니다. 왼쪽에는 다음과 같은 항목이 포함된 실습 세부정보 창이 있습니다.

    • Google Cloud 콘솔 열기 버튼
    • 남은 시간
    • 이 실습에 사용해야 하는 임시 사용자 인증 정보
    • 필요한 경우 실습 진행을 위한 기타 정보
  2. Google Cloud 콘솔 열기를 클릭합니다(Chrome 브라우저를 실행 중인 경우 마우스 오른쪽 버튼으로 클릭하고 시크릿 창에서 링크 열기를 선택합니다).

    실습에서 리소스가 가동되면 다른 탭이 열리고 로그인 페이지가 표시됩니다.

    팁: 두 개의 탭을 각각 별도의 창으로 나란히 정렬하세요.

    참고: 계정 선택 대화상자가 표시되면 다른 계정 사용을 클릭합니다.
  3. 필요한 경우 아래의 사용자 이름을 복사하여 로그인 대화상자에 붙여넣습니다.

    {{{user_0.username | "Username"}}}

    실습 세부정보 창에서도 사용자 이름을 확인할 수 있습니다.

  4. 다음을 클릭합니다.

  5. 아래의 비밀번호를 복사하여 시작하기 대화상자에 붙여넣습니다.

    {{{user_0.password | "Password"}}}

    실습 세부정보 창에서도 비밀번호를 확인할 수 있습니다.

  6. 다음을 클릭합니다.

    중요: 실습에서 제공하는 사용자 인증 정보를 사용해야 합니다. Google Cloud 계정 사용자 인증 정보를 사용하지 마세요. 참고: 이 실습에 자신의 Google Cloud 계정을 사용하면 추가 요금이 발생할 수 있습니다.
  7. 이후에 표시되는 페이지를 클릭하여 넘깁니다.

    • 이용약관에 동의합니다.
    • 임시 계정이므로 복구 옵션이나 2단계 인증을 추가하지 않습니다.
    • 무료 체험판을 신청하지 않습니다.

잠시 후 Google Cloud 콘솔이 이 탭에서 열립니다.

참고: Google Cloud 제품 및 서비스에 액세스하려면 탐색 메뉴를 클릭하거나 검색창에 제품 또는 서비스 이름을 입력합니다. 탐색 메뉴 아이콘 및 검색창

Cloud Shell 활성화

Cloud Shell은 다양한 개발 도구가 탑재된 가상 머신으로, 5GB의 영구 홈 디렉터리를 제공하며 Google Cloud에서 실행됩니다. Cloud Shell을 사용하면 명령줄을 통해 Google Cloud 리소스에 액세스할 수 있습니다.

  1. Google Cloud 콘솔 상단에서 Cloud Shell 활성화 Cloud Shell 활성화 아이콘를 클릭합니다.

  2. 다음 창을 클릭합니다.

    • Cloud Shell 정보 창을 통해 계속 진행합니다.
    • 사용자 인증 정보를 사용하여 Google Cloud API를 호출할 수 있도록 Cloud Shell을 승인합니다.

연결되면 사용자 인증이 이미 처리된 것이며 프로젝트가 학습자의 PROJECT_ID, (으)로 설정됩니다. 출력에 이 세션의 PROJECT_ID를 선언하는 줄이 포함됩니다.

Your Cloud Platform project in this session is set to {{{project_0.project_id | "PROJECT_ID"}}}

gcloud는 Google Cloud의 명령줄 도구입니다. Cloud Shell에 사전 설치되어 있으며 명령줄 자동 완성을 지원합니다.

  1. (선택사항) 다음 명령어를 사용하여 활성 계정 이름 목록을 표시할 수 있습니다.
gcloud auth list
  1. 승인을 클릭합니다.

출력:

ACTIVE: * ACCOUNT: {{{user_0.username | "ACCOUNT"}}} To set the active account, run: $ gcloud config set account `ACCOUNT`
  1. (선택사항) 다음 명령어를 사용하여 프로젝트 ID 목록을 표시할 수 있습니다.
gcloud config list project

출력:

[core] project = {{{project_0.project_id | "PROJECT_ID"}}} 참고: gcloud 전체 문서는 Google Cloud에서 gcloud CLI 개요 가이드를 참고하세요.

작업 1. 간단한 GKE 클러스터 만들기

  1. MY_ZONE이라는 환경 변수에 영역을 설정합니다. 이 실습에서는 ''을(를) 사용하고 있지만, 원한다면 다른 영역을 선택할 수 있습니다.
export MY_ZONE={{{project_0.default_zone|ZONE}}}
  1. 다음을 실행하여 Kubernetes Engine에서 관리되는 simplecluster라는 Kubernetes 클러스터를 시작하고, 2개 노드로 구성합니다.
gcloud container clusters create simplecluster --zone $MY_ZONE --num-nodes 2 --metadata=disable-legacy-endpoints=false

Kubernetes Engine이 가상 머신을 프로비저닝하므로 클러스터를 생성하는 데 몇 분 정도 걸립니다. 이 실습에서는 새 버전에서 제공되는 기능과 관련된 경고는 무시해도 괜찮습니다.

  1. 클러스터가 생성되면 kubectl version 명령어를 사용하여 설치된 Kubernetes 버전을 확인합니다.
kubectl version

gcloud container clusters create 명령어를 사용하면 kubectl이 자동으로 인증됩니다.

  1. Cloud 콘솔에서 실행 중인 노드를 확인합니다. 탐색 메뉴에서 Compute Engine > VM 인스턴스를 클릭합니다.

이제 Kubernetes 클러스터를 사용할 준비가 완료되었습니다.

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 간단한 GKE 클러스터 만들기

작업 2. Google Cloud SDK 포드 실행

  1. Cloud Shell 프롬프트에서 Google Cloud SDK 컨테이너 인스턴스를 하나 실행합니다.
kubectl run -it --rm gcloud --image=google/cloud-sdk:latest --restart=Never -- bash

완료되기까지 몇 분 정도 걸립니다.

참고: 시간 초과 오류가 발생하면 해당 명령어를 다시 실행합니다.
  1. 이제 포드의 컨테이너 내부에서 Bash 셸을 사용할 수 있어야 합니다.
root@gcloud:/#

컨테이너가 시작되고 명령 프롬프트가 표시되기까지 몇 초 정도 걸릴 수 있습니다. 명령 프롬프트가 보이지 않으면 Enter 키를 눌러 보세요.

Compute 메타데이터 엔드포인트 살펴보기

  1. 다음 명령어를 실행하여 v1 Compute 메타데이터 엔드포인트에 액세스합니다.
curl -s http://metadata.google.internal/computeMetadata/v1/instance/name

출력은 다음과 비슷합니다.

...snip... 클라이언트가 이 서버에서 URL /computeMetadata/v1/instance/name을 얻을 수 있는 권한이 없습니다. Metadata-Flavor:Google 헤더가 누락되었습니다. ...snip...

커스텀 HTTP 헤더가 있어야 한다는 오류가 반환되는 것을 확인합니다.

  1. 다음 실행에서는 커스텀 헤더를 추가하여, 이 포드를 실행 중인 Compute Engine 인스턴스 이름을 가져옵니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/name

출력은 다음과 비슷합니다.

gke-simplecluster-default-pool-b57a043a-6z5v 참고: Compute Engine 인스턴스 메타데이터 엔드포인트에 액세스할 때 커스텀 HTTP 헤더가 필요하지 않다면, 공격자는 애플리케이션 취약점만으로도 웹 URL을 속여 사용자 인증 정보를 제공하도록 만들 수 있습니다. 커스텀 HTTP 헤더를 요구하는 경우, 공격이 성공하려면 애플리케이션 취약점과 커스텀 헤더가 모두 필요하므로 공격이 더 어려워집니다.

다음 단계를 위해 포드 내부 셸을 종료하지 말고 그대로 유지하세요.

  1. 실수로 포드를 종료했다면 다음 명령어를 다시 실행하기만 하면 됩니다.
kubectl run -it --rm gcloud --image=google/cloud-sdk:latest --restart=Never -- bash

GKE 노드 부트스트랩 사용자 인증 정보 살펴보기

  1. 동일한 포드 셸 내부에서 다음 명령어를 실행하여, 기반이 되는 Compute Engine 인스턴스에 연결된 속성을 나열합니다. 끝의 슬래시를 포함해야 합니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/

이 목록에서 가장 민감한 정보는 kube-env일 가능성이 큽니다. 여기에는 kubelet이 노드를 GKE 클러스터에 연결할 때 초기 사용자 인증 정보로 사용하는 여러 변수가 포함됩니다. CA_CERT, KUBELET_CERT, KUBELET_KEY 변수에 이러한 정보가 포함되므로, 클러스터 관리자가 아닌 사용자에게는 민감 정보로 간주됩니다.

  1. 잠재적으로 민감한 변수와 데이터를 보려면 다음 명령어를 실행합니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env

따라서 다음과 같은 어떤 상황에서든,

  • 포드 애플리케이션에서 SSRF를 가능하게 하는 취약점이 있는 경우
  • 포드에서 RCE를 가능하게 하는 애플리케이션 또는 라이브러리 취약점이 있는 경우
  • 포드를 만들거나 포드에 exec로 들어갈 수 있는 권한을 가진 내부 사용자가 있는 경우

Compute 메타데이터 엔드포인트를 통해 민감한 kubelet 부트스트래핑 사용자 인증 정보가 침해되고 유출될 가능성이 매우 높습니다. kubelet 사용자 인증 정보를 확보하면, 특정 상황에서는 이를 악용하여 cluster-admin 수준으로 권한을 에스컬레이션할 수 있으며, 그 결과 모든 데이터와 애플리케이션을 포함한 GKE 클러스터 전체와 기반 노드에 대한 액세스까지 완전히 통제할 수 있게 됩니다.

이 노드 풀의 서비스 계정에 할당된 권한 활용

기본적으로 Compute API가 사용 설정된 Google Cloud 프로젝트에는 NNNNNNNNNN-compute@developer.gserviceaccount.com 형식의 기본 서비스 계정이 존재하며, 이 계정에는 Editor 역할이 할당되어 있습니다. 또한 기본적으로 서비스 계정을 지정하지 않고 생성된 GKE 클러스터는 기본 Compute 서비스 계정을 사용하며 이를 모든 워커 노드에 연결합니다.

  1. 다음 curl 명령어를 실행하여 기반이 되는 Compute Engine 인스턴스에 연결된 서비스 계정의 OAuth 범위를 나열합니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes

(출력) https://www.googleapis.com/auth/devstorage.read_only https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/monitoring https://www.googleapis.com/auth/service.management.readonly https://www.googleapis.com/auth/servicecontrol https://www.googleapis.com/auth/trace.append

인증 범위와 서비스 계정의 권한 조합에 따라 이 노드에서 실행되는 애플리케이션이 액세스할 수 있는 리소스가 결정됩니다. 위 목록은 대부분의 GKE 클러스터에 필요한 최소 범위이지만, 일부 사용 사례에서는 더 넓은 범위가 필요할 수 있습니다.

경고: 클러스터 생성 시 인증 범위에 `https://www.googleapis.com/auth/cloud-platform`을 포함하도록 설정했다면 모든 Google Cloud API가 범위에 포함되며, 액세스 가능 여부는 서비스 계정에 할당된 IAM 권한에 의해서만 결정됩니다.

더 나아가, 기본 IAM 역할인 Editor가 할당된 기본 서비스 계정을 사용하고 있다면 이 노드 풀에서 실행되는 모든 포드는 GKE 클러스터가 배포된 Google Cloud 프로젝트에 대해 Editor 권한을 갖게 됩니다. Editor IAM 역할은 Compute 인스턴스, Cloud Storage 버킷, GCR 레지스트리 등 프로젝트 리소스와 상호작용할 수 있는 광범위한 읽기/쓰기 권한을 가지므로 이는 매우 중대한 보안 위험입니다.
  1. 다음을 입력하여 이 포드에서 나갑니다.
exit 참고: Cloud Shell로 돌아오지 않았다면 Ctrl+C를 누르세요.

작업 3. 호스트 파일 시스템을 마운트하는 포드 배포

기반이 되는 호스트로 '이스케이프'하는 가장 간단한 방법 중 하나는 Pod 사양에서 표준 Kubernetes volumesvolumeMounts를 사용해 호스트의 파일 시스템을 포드의 파일 시스템에 마운트하는 것입니다.

  1. 이를 시연하기 위해 다음을 실행하여 기본 호스트의 파일 시스템(/)을 컨테이너 내부의 /rootfs라는 폴더에 마운트하는 포드를 만듭니다.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: hostpath spec: containers: - name: hostpath image: google/cloud-sdk:latest command: ["/bin/bash"] args: ["-c", "tail -f /dev/null"] volumeMounts: - mountPath: /rootfs name: rootfs volumes: - name: rootfs hostPath: path: / EOF
  1. 포드 상태가 '실행 중'이 될 때까지 kubectl get pod 명령어를 반복해서 실행합니다.
kubectl get pod

(출력)

NAME READY STATUS RESTARTS AGE hostpath 1/1 Running 0 30s

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 호스트 파일 시스템을 마운트하는 포드 배포

작업 4. 기본 호스트 탐색 및 침해

  1. 다음을 실행하여 방금 만든 포드 내부에서 셸에 액세스합니다.
kubectl exec -it hostpath -- bash
  1. 포드 셸의 루트 파일 시스템을 기본 호스트의 루트 파일 시스템으로 전환합니다.
chroot /rootfs /bin/bash

이 간단한 명령어만으로도 이제 이 포드는 노드에서 사실상 root 셸을 확보한 것과 같습니다. 이제 다음 작업을 수행할 수 있습니다.

전체 권한으로 표준 Docker 명령어 실행

docker ps

Docker 이미지 목록 확인

docker images

원하는 권한 있는 컨테이너를 docker run으로 실행

docker run --privileged <imagename>:<imageversion>

마운트된 Kubernetes 보안 비밀 확인

mount | grep volumes | awk '{print $3}' | xargs ls

실행 중인 어떤 컨테이너든 exec로 액세스(다른 네임스페이스의 다른 포드까지 포함)

docker exec -it <docker container ID> sh

root 사용자가 수행할 수 있는 거의 모든 작업을 이 포드 셸에서도 수행할 수 있습니다. 여기에는 SSH 사용자/키 추가와 같은 지속성 메커니즘, Kubernetes의 관측 범위 밖에서 호스트에 권한이 있는 Docker 컨테이너를 실행하는 작업 등도 포함되며 그 외에도 더 많은 작업이 가능합니다.

  1. 포드 셸을 종료하려면 exit를 두 번 실행합니다. 한 번은 chroot에서 빠져나오기 위해, 또 한 번은 포드 셸을 종료하기 위해 실행합니다.
exit exit 참고: Cloud Shell로 돌아오지 않았다면 Ctrl+C를 누르세요.
  1. 이제 hostpath 포드를 삭제할 수 있습니다.
kubectl delete pod hostpath

사용 가능한 제어 수단 이해하기

이 데모의 다음 단계에서는 다음 내용을 다룹니다.

  • 레거시 Compute Engine Metadata API 엔드포인트 사용 중지 - 커스텀 메타데이터 키와 값을 지정하면 v1beta1 메타데이터 엔드포인트를 인스턴스에서 더 이상 사용할 수 없게 됩니다.
  • 메타데이터 숨김 사용 설정 - 클러스터 또는 노드 풀 생성 시 추가 구성을 전달하면 각 노드에 경량 프록시가 설치되어 메타데이터 API로 향하는 모든 요청을 프록시 처리하고 민감한 엔드포인트에 대한 액세스를 차단합니다.
  • 포드 보안 허용 사용 설정 및 활용 - GKE 클러스터에서 포드 보안 허용(PSA) 컨트롤러를 사용 설정합니다. 이를 통해 클러스터의 보안 상황을 강화하는 포드 보안 표준을 강제 적용할 수 있습니다.

작업 5. 두 번째 노드 풀 배포

메타데이터 엔드포인트 보호 설정이 있는 경우와 없는 경우를 실험할 수 있도록 두 가지 추가 설정이 포함된 두 번째 노드 풀을 만듭니다. 기본 노드 풀에 예약된 포드에는 보호가 적용되지 않으며 두 번째 노드 풀에 예약된 포드에는 보호가 사용 설정됩니다.

참고: 레거시 엔드포인트는 2020년 9월 30일에 지원 중단되었습니다. GKE 버전 1.12 이상에서는 `--metadata=disable-legacy-endpoints=true` 설정이 기본적으로 사용 설정됩니다. 아래 명령어에서는 이해를 돕기 위해 이를 명시적으로 지정합니다.
  • 두 번째 노드 풀을 만듭니다.
gcloud beta container node-pools create second-pool --cluster=simplecluster --zone=$MY_ZONE --num-nodes=1 --metadata=disable-legacy-endpoints=true --workload-metadata-from-node=SECURE

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 두 번째 노드 풀 배포

작업 6. Google Cloud SDK 포드 실행

  1. Cloud Shell에서 보호 설정이 사용 설정된 두 번째 노드 풀에서만 실행되며 루트 사용자로 실행되지 않는 Google Cloud-SDK 컨테이너 인스턴스를 하나 실행합니다.
kubectl run -it --rm gcloud --image=google/cloud-sdk:latest --restart=Never --overrides='{ "apiVersion": "v1", "spec": { "securityContext": { "runAsUser": 65534, "fsGroup": 65534 }, "nodeSelector": { "cloud.google.com/gke-nodepool": "second-pool" } } }' -- bash 참고: 시간 초과 오류가 발생하면 명령어를 다시 실행합니다.
  1. 이제 second-pool이라는 노드 풀에서 실행 중인 포드의 컨테이너 내부에서 Bash 셸을 사용할 수 있어야 합니다. 아래와 같이 표시됩니다.
nobody@gcloud:/$

컨테이너가 시작되고 명령 프롬프트가 열리기까지 몇 초 정도 걸릴 수 있습니다.

명령 프롬프트가 보이지 않으면 Enter 키를 누릅니다.

차단된 다양한 엔드포인트 살펴보기

  1. 두 번째 노드 풀을 --workload-metadata-from-node=SECURE로 구성했기 때문에, 민감한 파일인 kube-env를 가져오기 위한 다음 명령어는 이제 실패합니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env

(출력)

이 메타데이터 엔드포인트는 숨김 처리되었습니다.
  1. 하지만 민감하지 않은 엔드포인트에 대해서는 적절한 HTTP 헤더를 전달하면 다른 명령어는 여전히 성공합니다.
curl -s -H "Metadata-Flavor: Google" http://metadata.google.internal/computeMetadata/v1/instance/name

(출력 예시)

gke-simplecluster-second-pool-8fbd68c5-gzzp
  1. 포드에서 나옵니다.
exit

이제 Cloud Shell로 돌아와 있어야 합니다.

작업 7. 포드 보안 표준 강제 적용

  1. 다음 단계를 진행하기 위해 필요한 권한을 확보하려면, 자신의 사용자 계정에 cluster-admin 권한을 명시적으로 부여하세요.
kubectl create clusterrolebinding clusteradmin --clusterrole=cluster-admin --user="$(gcloud config list account --format 'value(core.account)')"

(출력)

clusterrolebinding.rbac.authorization.k8s.io/clusteradmin created
  1. 이제 포드 보안 표준을 강제 적용합니다. 'default' 네임스페이스에서 가장 적합한 보안 표준을 선택합니다. 'restricted' 프로필은 더 강력한 보안을 제공합니다.
kubectl label namespace default pod-security.kubernetes.io/enforce=restricted
  1. 다음으로 ClusterRole을 만듭니다. 네임스페이스에서 포드 보안 허용 수준을 변경할 수 있는 사용자를 제어하려면 pod-security-manager라는 ClusterRole을 만듭니다.
cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pod-security-manager rules: - apiGroups: ['policy'] resources: ['podsecuritypolicies'] resourceNames: ['privileged', 'baseline', 'restricted'] verbs: ['use'] - apiGroups: [''] resources: ['namespaces'] verbs: ['get', 'list', 'watch', 'label'] EOF
  1. 다음으로 RoleBinding을 만듭니다. 포드 보안 허용과 관련된 네임스페이스 라벨을 변경할 수 있는 사용자를 제한하려면 'default' 네임스페이스에 RoleBinding을 만듭니다.
cat <<EOF | kubectl apply -f - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: pod-security-modifier namespace: default subjects: - kind: Group apiGroup: rbac.authorization.k8s.io name: system:authenticated roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: pod-security-manager EOF 참고: 보다 고도로 맞춤설정되고 동적인 포드 보안 강제가 필요하다면 OPA Gatekeeper 또는 Kyverno와 같은 도구를 고려하세요.

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. PodSecurityPolicy 객체 배포

작업 8. 호스트 파일 시스템을 마운트하는 차단된 포드 배포

이전 단계에서 GKE 클러스터를 배포한 계정에 cluster-admin 권한이 부여되었기 때문에 PodSecurityPolicy 적용 여부를 검증하려면 클러스터와 상호작용할 별도의 '사용자' 계정을 만들어야 합니다.

  1. 이렇게 하려면 다음 명령어를 실행합니다.
gcloud iam service-accounts create demo-developer

(출력)

Created service account [demo-developer].
  1. 다음으로, 이 서비스 계정이 클러스터와 상호작용하고 포드 생성을 시도할 수 있도록 권한을 부여하기 위해 아래 명령어를 실행합니다.
MYPROJECT=$(gcloud config list --format 'value(core.project)') gcloud projects add-iam-policy-binding "${MYPROJECT}" --role=roles/container.developer --member="serviceAccount:demo-developer@${MYPROJECT}.iam.gserviceaccount.com"
  1. 다음 명령어를 실행하여 서비스 계정 사용자 인증 정보 파일을 가져옵니다.
gcloud iam service-accounts keys create key.json --iam-account "demo-developer@${MYPROJECT}.iam.gserviceaccount.com"
  1. kubectl이 이 서비스 계정으로 인증하도록 구성합니다.
gcloud auth activate-service-account --key-file=key.json
  1. kubectl이 클러스터와 통신할 때 이 사용자 인증 정보를 사용하도록 구성하려면 다음을 실행합니다.
gcloud container clusters get-credentials simplecluster --zone $MY_ZONE
  1. 이제 컨테이너 내부의 /rootfs 폴더에 기본 호스트 파일 시스템(/)을 마운트하는 또 다른 포드를 만들어 보세요.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: hostpath spec: containers: - name: hostpath image: google/cloud-sdk:latest command: ["/bin/bash"] args: ["-c", "tail -f /dev/null"] volumeMounts: - mountPath: /rootfs name: rootfs volumes: - name: rootfs hostPath: path: / EOF
  1. 다음 출력은 포드 보안 표준에 의해 차단되었음을 검증합니다.
Error from server (Forbidden): error when creating "STDIN": pods "hostpath" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "hostpath" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "hostpath" must set securityContext.capabilities.drop=["ALL"]), restricted volume types (volume "rootfs" uses restricted volume type "hostPath"), runAsNonRoot != true (pod or container "hostpath" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "hostpath" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
  1. restrictive-psp 기준을 충족하는 또 다른 포드를 배포합니다.
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Pod metadata: name: hostpath spec: securityContext: runAsNonRoot: true # Ensure a non-root user runAsUser: 1000 fsGroup: 2000 seccompProfile: # Add a seccomp profile type: RuntimeDefault containers: - name: hostpath image: google/cloud-sdk:latest command: ["/bin/bash"] args: ["-c", "tail -f /dev/null"] securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] EOF

(출력)

pod/hostpath created

내 진행 상황 확인하기를 클릭하여 목표를 확인합니다. 호스트 파일 시스템을 마운트하는 차단된 포드 배포

수고하셨습니다

이 실습에서는 Google Kubernetes Engine에서 기본 Kubernetes 클러스터를 구성했습니다. 그 후 포드에 허용된 액세스 권한을 탐색하고 이를 악용한 다음 클러스터를 강화하고, 그러한 악의적인 동작이 더 이상 가능하지 않음을 검증했습니다.

다음 단계/더 학습하기

Google Cloud 교육 및 자격증

Google Cloud 기술을 최대한 활용하는 데 도움이 됩니다. Google 강의에는 빠른 습득과 지속적인 학습을 지원하는 기술적인 지식과 권장사항이 포함되어 있습니다. 기초에서 고급까지 수준별 학습을 제공하며 바쁜 일정에 알맞은 주문형, 실시간, 가상 옵션이 포함되어 있습니다. 인증은 Google Cloud 기술에 대한 역량과 전문성을 검증하고 입증하는 데 도움이 됩니다.

설명서 최종 업데이트: 2024년 2월 14일

실습 최종 테스트: 2024년 2월 14일

Copyright 2026 Google LLC. All rights reserved. Google 및 Google 로고는 Google LLC의 상표입니다. 기타 모든 회사명 및 제품명은 해당 업체의 상표일 수 있습니다.

시작하기 전에

  1. 실습에서는 정해진 기간 동안 Google Cloud 프로젝트와 리소스를 만듭니다.
  2. 실습에는 시간 제한이 있으며 일시중지 기능이 없습니다. 실습을 종료하면 처음부터 다시 시작해야 합니다.
  3. 화면 왼쪽 상단에서 실습 시작을 클릭하여 시작합니다.

시크릿 브라우징 사용

  1. 실습에 입력한 사용자 이름비밀번호를 복사합니다.
  2. 비공개 모드에서 콘솔 열기를 클릭합니다.

콘솔에 로그인

    실습 사용자 인증 정보를 사용하여
  1. 로그인합니다. 다른 사용자 인증 정보를 사용하면 오류가 발생하거나 요금이 부과될 수 있습니다.
  2. 약관에 동의하고 리소스 복구 페이지를 건너뜁니다.
  3. 실습을 완료했거나 다시 시작하려고 하는 경우가 아니면 실습 종료를 클릭하지 마세요. 이 버튼을 클릭하면 작업 내용이 지워지고 프로젝트가 삭제됩니다.

현재 이 콘텐츠를 이용할 수 없습니다

이용할 수 있게 되면 이메일로 알려드리겠습니다.

감사합니다

이용할 수 있게 되면 이메일로 알려드리겠습니다.

한 번에 실습 1개만 가능

모든 기존 실습을 종료하고 이 실습을 시작할지 확인하세요.

시크릿 브라우징을 사용하여 실습 실행하기

이 실습을 실행하는 가장 좋은 방법은 시크릿 모드 또는 시크릿 브라우저 창을 사용하는 것입니다. 개인 계정과 학생 계정 간의 충돌로 개인 계정에 추가 요금이 발생하는 일을 방지해 줍니다.