이 가이드에서는 Google Kubernetes Engine (GKE)이 제어 평면 VM에 사용하는 Compute Engine 가상 머신 (VM) 이미지의 무결성을 확인하는 방법을 설명합니다. 이 가이드는 제어 플레인 로그를 모니터링하고 다음을 확인하려는 보안팀을 위해 작성되었습니다.
- 제어 평면 VM은 보안 부팅 및 무결성 모니터링으로 암호화 방식으로 확인된 신뢰할 수 있는 펌웨어 및 기타 부팅 소프트웨어로 부팅되었습니다.
- 제어 평면 VM이 실제 GKE OS 이미지에서 부팅되었습니다.
워커 노드의 OS 이미지 및 부팅 무결성에 대해 이 확인을 실행할 수도 있습니다.
이 페이지에서는 GKE의 선택적 제어 영역 기능 세트 중 하나를 설명합니다. 이 기능을 사용하면 제어 영역 보안 상태를 확인하거나 관리하는 키를 사용하여 제어 영역에서 암호화 및 사용자 인증 정보 서명을 구성하는 등의 작업을 실행할 수 있습니다. 자세한 내용은 GKE 제어 영역 권한 정보를 참고하세요.
기본적으로 Google Cloud 는 관리 컨트롤 플레인에 다양한 보안 조치를 적용합니다. 이 페이지에서는 GKE 제어 영역을 더 잘 확인하거나 제어할 수 있는 선택적 기능을 설명합니다.
VM 무결성 확인 정보
기본적으로 모든 GKE 제어 플레인 인스턴스는 보호된 VM입니다. 보호된 VM은 안전하고 신중한 부팅, Virtual Trusted Platform Module (vTPM), UEFI 펌웨어와 같은 보안 기능을 사용하는 강화된 VM입니다. 또한 모든 GKE 노드는 각 보안 VM의 부팅 시퀀스를 기준 '양호' 부팅 시퀀스와 비교하여 검증하는 무결성 모니터링을 사용 설정합니다. 이 유효성 검사는 각 부팅 시퀀스 단계의 통과 또는 실패 결과를 반환하고 이러한 결과를 Cloud Logging에 추가합니다. 무결성 모니터링은 모든 GKE 클러스터에서 기본적으로 사용 설정되며 다음 단계를 검증합니다.
- 초기 부팅 시퀀스: UEFI 펌웨어가 시작된 시점부터 부트로더가 제어권을 가져올 때까지의 시퀀스입니다. VM 로그에
earlyBootReportEvent
로 추가되었습니다. - 후기 부팅 시퀀스: 부트로더가 제어권을 가져올 때부터 운영체제 커널이 제어권을 가져올 때까지입니다. VM 로그에
lateBootReportEvent
로 추가되었습니다.
또한 GKE는 Logging에 컨트롤 플레인 VM 생성 로그를 추가합니다. 이러한 로그에는 머신을 식별하는 메타데이터가 포함되며 VM 이미지 및 부팅 시퀀스에 관한 세부정보가 포함됩니다. Google Cloud 는 각 GKE 제어 영역 VM 이미지의 확인 요약 증명 (VSA)을 GitHub의 gke-vsa 저장소에 게시합니다. VSA는 증명에 in-toto 프레임워크를 사용합니다. 클러스터의 제어 영역 VM 로그를 상응하는 VSA와 비교하여 제어 영역 노드가 예상대로 부팅되었는지 확인할 수 있습니다.
이러한 유효성 검사를 실행하면 다음과 같은 목표를 달성하는 데 도움이 됩니다.
- 제어 영역의 소프트웨어가 안전한 부팅 및 무결성 모니터링으로 보호되고, 의도한 소스 코드와 일치하며, 다른 Google Cloud 고객이 사용하는 이미지와 정확히 동일한지 확인합니다.
- GKE가 컨트롤 플레인을 보호하는 방식에 대한 신뢰도를 높입니다.
가격 책정
이 기능은 GKE에서 추가 비용 없이 제공됩니다.
시작하기 전에
시작하기 전에 다음 태스크를 수행했는지 확인합니다.
- Google Kubernetes Engine API를 사용 설정합니다. Google Kubernetes Engine API 사용 설정
- 이 태스크에 Google Cloud CLI를 사용하려면 gcloud CLI를 설치한 후 초기화하세요. 이전에 gcloud CLI를 설치한 경우
gcloud components update
를 실행하여 최신 버전을 가져옵니다.
-
Enable the Cloud Logging API.
- 버전 1.29 이상을 실행하는 GKE Autopilot 모드 또는 표준 모드 클러스터가 이미 있는지 확인합니다.
필요한 역할
제어 플레인 VM 무결성을 확인하는 데 필요한 권한을 얻으려면 관리자에게 프로젝트에 대한 다음 IAM 역할을 부여해 달라고 요청하세요.
-
클러스터 만들기 및 상호작용:
Kubernetes Engine 클러스터 관리자 (
roles/container.clusterAdmin
) -
로그 액세스 및 처리:
로그 뷰어 (
roles/logging.viewer
)
역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
실패한 부팅 시퀀스 단계 확인
무결성 모니터링은 제어 평면 VM이 실패하거나 부팅 시퀀스의 단계를 성공적으로 완료하면 Logging에 로그를 추가합니다. 실패한 부팅 이벤트를 보려면 다음 명령어를 실행합니다.
Google Cloud 콘솔에서 로그 탐색기 페이지로 이동합니다.
쿼리 필드에 다음 쿼리를 지정합니다.
jsonPayload.@type="type.googleapis.com/cloud_integrity.IntegrityEvent" jsonPayload.earlyBootReportEvent.policyEvaluationPassed="false" OR jsonPayload.lateBootReportEvent.policyEvaluationPassed="false" jsonPayload.metadata.isKubernetesControlPlaneVM="true"
이 쿼리에서
false
를true
로 대체하여 부팅 이벤트가 성공적으로 실행되었는지 확인할 수도 있습니다.쿼리 실행을 클릭합니다. 결과가 표시되지 않으면 제어 영역 VM이 모든 무결성 모니터링 검사를 통과한 것입니다. 출력이 표시되면 다음 단계로 진행하여 해당 클러스터를 식별합니다.
부팅 무결성 실패 로그에서
resource.labels.instance_id
필드의 값을 복사합니다.쿼리 필드에 다음 쿼리를 지정합니다.
protoPayload.@type="type.googleapis.com/google.cloud.audit.AuditLog" protoPayload.metadata.isKubernetesControlPlaneVM="true" resource.labels.instance_id="INSTANCE_ID" protoPayload.methodName="v1.compute.instances.insert"
INSTANCE_ID
를 이전 단계의instance_id
필드 값으로 바꿉니다.쿼리 실행을 클릭합니다.
protoPayload.metadata.parentResource.parentResourceId
필드의 값은 GKE 클러스터 ID입니다.GKE 클러스터의 이름을 찾습니다.
gcloud asset query \ --organization=ORGANIZATION_ID \ --statement="SELECT name FROM container_googleapis_com_Cluster WHERE resource.data.id='CLUSTER_ID';"
다음을 바꿉니다.
ORGANIZATION_ID
:Google Cloud 조직의 숫자 ID입니다.CLUSTER_ID
: 이전 단계의protoPayload.metadata.parentResource.parentResourceId
필드 값입니다.
출력은 다음과 비슷합니다.
# lines omitted for clarity //container.googleapis.com/projects/PROJECT_ID/locations/LOCATION/clusters/CLUSTER_NAME
이 출력에는 다음 필드가 포함됩니다.
PROJECT_ID
: Google Cloud 프로젝트 ID입니다.LOCATION
: 클러스터의 위치입니다.CLUSTER_NAME
: 클러스터의 이름입니다.
제어 영역 VM 로그 찾기 및 검사
GKE 클러스터에 해당하는 Compute Engine VM 생성 로그는 _Default
로그 버킷에 저장됩니다.
클러스터 컨트롤 플레인 VM의 생성 로그를 찾아 이 메타데이터를 검색하려면 다음 단계를 따르세요.
Google Cloud 콘솔에서 로그 탐색기 페이지로 이동합니다.
쿼리 필드에 다음 쿼리를 지정합니다.
resource.type="gce_instance" protoPayload.methodName="v1.compute.instances.insert" protoPayload.metadata.isKubernetesControlPlaneVM="true"
쿼리 실행을 클릭합니다. 결과가 표시되지 않으면 시작하기 전에 섹션의 모든 요구사항을 충족하는지 확인하세요.
쿼리 결과에서
metadata
필드를 확인합니다. 출력은 다음과 비슷합니다.# fields omitted for clarity "metadata": { "usedResources": { "attachedDisks": [ { "sourceImageId": "9046093115864736653", "sourceImage": "https://www.googleapis.com/compute/v1/projects/1234567890/global/images/gke-1302-gke1627000-cos-113-18244-85-49-c-pre", "isBootDisk": true } # fields omitted for clarity
metadata
필드에는 다음 정보가 포함됩니다.usedResources
: VM을 만드는 데 사용된 리소스 목록입니다.attachedDisks
: VM의 부팅 디스크입니다.sourceImageId
: VM 이미지의 고유 ID입니다.sourceImage
: 소스 VM 이미지의 URL입니다. 이 필드의 값 문법은https://www.googleapis.com/compute/v1/projects/PROJECT_NUMBER/global/images/IMAGE_NAME
입니다. 여기서PROJECT_NUMBER
는 제어 평면 VM을 호스팅하는Google Cloud소유 프로젝트의 번호이고IMAGE_NAME
는 VM 부팅에 사용된 이미지의 이름입니다.isBootDisk
: 이 디스크가 VM의 부팅 디스크로 사용되었는지 여부를 나타내는 불리언 식별자입니다.
제어 영역 VM 이미지의 VSA 찾기 및 확인
이 섹션에서는 GitHub의 gke-vsa 저장소에서 제어 영역 VM 이미지에 해당하는 VSA를 찾습니다. 그런 다음 소프트웨어 아티팩트에 대한 공급망 수준 (SLSA) 프레임워크에서 제공하는 slsa-verifier
라는 도구를 사용하여 VSA를 확인합니다. 제어 영역 VM 생성 로그에서 다음 데이터가 필요합니다.
- VM 이미지 ID
- VM을 호스팅하는 Google Cloud소유 프로젝트의 프로젝트 번호입니다.
- VM을 부팅하는 데 사용된 OS 이미지 이름
제어 영역 VM에 해당하는 파일의 파일 이름 형식은 다음과 같습니다.
IMAGE_NAME:IMAGE_ID.intoto.jsonl
다음을 바꿉니다.
IMAGE_NAME
: VM 이미지 이름입니다. 이전 섹션의 VM 감사 로그에 있는attachedDisks.sourceImage
필드에서/images/
뒤에 오는 문자열입니다. 예를 들면gke-1302-gke1627000-cos-113-18244-85-49-c-pre
입니다.IMAGE_ID
: VM 이미지 ID입니다. 이는 이전 섹션의 VM 감사 로그에 있는attachedDisks.sourceImageId
필드의 값입니다. 예를 들면9046093115864736653
입니다.
VSA 파일의 파일 이름을 알고 있는 경우 VSA를 찾아 확인하려면 다음 단계를 따르세요.
gke-vsa
GitHub 저장소를 엽니다.- 'gke-master-images' 디렉터리에서 VM 이미지에 해당하는 파일을 찾습니다. 예를 들면
https://github.com/GoogleCloudPlatform/gke-vsa/blob/main/gke-master-images:78064567238/IMAGE_NAME:IMAGE_ID.intoto.jsonl
입니다. - VSA 파일을 다운로드합니다.
slsa-verifier
도구를 설치합니다.VSA 확인을 위한 공개 키를
vsa_signing_public_key
파일에 저장합니다.VSA를 확인합니다.
slsa-verifier verify-vsa \ --attestation-path=PATH_TO_VSA_FILE \ --resource-uri=gce_image://gke-master-images:IMAGE_NAME \ --subject-digest=gce_image_id:IMAGE_ID\ --verifier-id=https://bcid.corp.google.com/verifier/bcid_package_enforcer/v0.1 \ --verified-level=BCID_L1 \ --verified-level=SLSA_BUILD_LEVEL_2 \ --public-key-path=PATH_TO_PUBLIC_KEY_FILE \ --public-key-id=keystore://76574:prod:vsa_signing_public_key
다음을 바꿉니다.
PATH_TO_VSA_FILE
: 다운로드한 VSA 파일의 경로입니다.IMAGE_NAME
: VM 이미지의 이름입니다(예:gke-1302-gke1627000-cos-113-18244-85-49-c-pre
).IMAGE_ID
: VM 이미지 ID입니다(예:9046093115864736653
).
VSA가 인증 확인을 통과하면 다음과 같이 출력됩니다.
Verifying VSA: PASSED PASSED: SLSA verification passed