GCP Instance Metadata를 100% 활용하는 방법
GCP는 VM 인스턴스의 메타데이터를 메타데이터 서버가 따로 관리하고 있습니다.
우리가 GCP를 사용하다보면 이 메타데이터 서버의 존재를 인지할 수 있는데요.
VM 인스턴스에서 트래픽 이동 경로를 확인하다보면 169.254.169.254 주소를 목적지로 하는 경우가 가끔 있는 것을 보신 분들이 있을 겁니다.
혹은 다른 클라우드 서비스에서 인스턴스에 메타데이터 서버를 따로 저장한다는 사실을 알고 계실 수도 있습니다.
GCP도 타 클라우드 서비스와 마찬가지로 169.254.169.254 주소가 바로 메타데이터 서버의 주소입니다.
하지만 메타데이터 서버의 존재만 알고 그 안에 저장된 메타데이터는 무엇이 있는지 모르는 분도 많은 것 같습니다.
이 메타데이터를 활용하면 알기 어려웠던 정보를 알 수 있을 뿐더러 스크립트를 통해 자동화를 편리하게 구성할 수 있습니다.
이번 포스팅에서는 메타데이터 서버가 무슨 역할을 하는지, 이 메타데이터 서버를 어떻게 활용할 수 있는지, 혹은 보안상 위험은 없는지
알아보도록 하겠습니다.
1. 메타데이터 서버란?
메타데이터 서버에 대해서 알아보기 전에 메타데이터가 무엇인지부터 알아야겠죠.
메타데이터는 데이터에 대한 데이터를 의미합니다. 흔히 볼 수 있는 파일의 생성일이나 수정날짜, 크기 등이 메타데이터에 속합니다.
그럼 GCP VM 인스턴스가 가질 수 있는 메타데이터는 무엇이 있을까요?
GCP Document에 따르면, 메타데이터 서버가 가진 데이터는 2가지로 나뉩니다.
1) 프로젝트 메타데이터 : 인스턴스를 포함하고 있는 프로젝트에 대한 메타데이터입니다. 프로젝트 ID, 프로젝트 기본 리젼, 존이 여기에 속합니다.
2) 인스턴스 메타데이터 : 문자 그대로 인스턴스에 대한 메타데이터입니다. 인스턴스가 가진 디스크, 서비스 어카운트, 머신 타입 등.. 다양한 메타데이터가 존재합니다.
두 메타데이터 중 이번 포스팅에서 주목할 것은 2번 인스턴스 메타데이터입니다.
인스턴스 메타데이터는 위에서 언급한 내용 말고도 다양한 정보를 담고 있습니다.
이제 어떻게 이 정보를 확인하고 활용할 수 있는지 알아봅시다.
2. 메타데이터를 조회하는법
GCP 인스턴스 메타데이터는 API를 통해 접근할 수 있습니다.
메타데이터를 조회하기 위해서는 다음 URL로 질의문을 보내야 합니다.
http://metadata.google.internal/computeMetadata/v1/
왜 중요한 데이터를 제공하는 URL이 HTTPS가 아닌 HTTP 프로토콜로 접근을 허용하지? 라는 의문을 일단 뒤로한채 메타데이터를 가져오는 방법에 대해서 더 알아봅시다.
CLI 환경에서 API에 접근하기 위해 주로 사용되는 명령어로 "curl" 이 있습니다. 이번 포스팅에서는 curl을 통해서 메타데이터를 조회합니다.
본격적으로 메타데이터를 조회하기 전에 주의해야 할 점 2가지가 있습니다.
1) 반드시 조회하고자 하는 인스턴스 내에서 접근해야 한다 :
어떤 인스턴스의 메타데이터는 다른 인스턴스나 로컬 환경에서 접근할 수 없습니다. 민감한 정보가 가득 들어있는 메타데이터를 외부에서 접근할 수 있다면 보안적으로 큰 결함일 것입니다.
2) 요청 시 "Metadata-Flavor: Google" 헤더와 함께 요청해야 한다 :
위와 마찬가지로 보안 정책과 관련된 주의사항입니다. 이 헤더는 해당 요청이 다른 목적이 아니라 메타데이터 조회를 목적으로 하는 요청임을 분명히 합니다. 이 헤더가 제공되지 않은 요청은 모두 거부됩니다.
이제 본격적으로 메타데이터 서버에 질의문을 요청해 보겠습니다.
다음은 Cloud Shell 환경에서 메타데이터 서버를 조회해 인스턴스의 0번 디스크 타입을 질의한 결과입니다.
curl -w "\n" "http://metadata.google.internal/computeMetadata/v1/instance/disks/0/type" -H "Metadata-Flavor: Google"
-w 플래그 뒤의 "\n"는 응답으로 돌아온 json 텍스트를 줄바꿈과 함께 응답하도록 하는데 필요하다.
위 명령어의 응답으로 PERSISENT-SSD가 돌아왔습니다.
이는 Cloud Shell이 사용하는 0번 디스크는 Persistent SSD 디스크 타입이라는 뜻입니다.
이렇게 디렉토리 형식의 URL을 조회하는 방식으로 메타데이터 서버에 저장된 메타데이터를 조회할 수 있습니다.
URL이 디렉토리 형식을 취하고 있기 때문에 "http://metadata.google.internal/computeMetadata/v1/instance/" 뒤에 원하는 디렉토리를 추가하면 원하는 메타데이터를 조회할 수 있습니다.
끝에 슬래쉬("/")가 붙은 응답은 다음으로 올 수 있는 디렉터리를 뜻합니다. 이것으로 쉽게 다음에 올 디렉토리 경로를 찾을 수도 있습니다.
다음은 인스턴스의 0번 NIC에 해당하는 메타데이터의 디렉토리를 질의하는 명령어입니다.
curl -w "\n" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0" -H "Metadata-Flavor: Google"
응답으로 뒤에 슬래쉬가 붙은 항목이 포함된 것을 볼 수 있습니다. 이 항목들은 모두 다음 경로에 올 수 있는 디렉토리입니다.
이렇게 문서를 참고하는 수고 없이 메타데이터 서버의 디렉토리 구조를 쉽게 조회할 수 있습니다.
3. 메타데이터를 100% 활용하는 방법
간단하게 Curl을 사용해서 메타데이터 서버에서 메타데이터를 조회해봤습니다.
그럼 이 메타데이터를 어디에, 어떻게 활용할 수 있을까요?
1. VM의 External IP 확인
GCP의 VM 인스턴스는 자신의 외부 IP를 알지 못합니다.
기본적으로 GCP는 VM의 외부 IP를 내부 IP와 1:1 NAT로 맵핑해서 사용하기 때문인데요.
그래서 VM에 접속한 상태로는 자신의 외부 IP를 확인할 수 없었습니다.
gcloud 커맨드로 확인하는 방법도 있지만 "--format" 플래그를 동반하기 때문에 쉬운 명령어가 아닙니다.
하지만 메타데이터 서버에 저장된 VM의 외부 IP 정보를 조회하는 방법으로 쉽게 알 수 있습니다.
다음은 VM의 외부 IP를 확인하는 명령어입니다.
curl -w "\n" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip" -H "Metadata-Flavor: Google"
이렇게 응답으로 IP주소가 온 것을 확인할 수 있습니다.
응답으로 온 IP주소가 실제 VM의 External IP와 일치합니다. 이렇게 메타데이터 서버를 조회해 VM의 외부 IP주소를 VM내에서도 확인할 수 있습니다.
2. 재귀적 질의
앞서 메타데이터 서버가 디렉토리 구조로 이루어져 있는 것을 확인했습니다.
그래서 원하는 정보가 존재하는 디렉토리를 찾기 위해서는 디렉토리 구조 마다 일일이 질의문을 요청해야 하는 번거로움이 있습니다.
재귀적 질의를 이용하면 이런 번거로움을 덜 수 있습니다.
재귀적 질의는 URL 디렉토리 끝에 "recursive=true" 파라미터를 붙이면 사용할 수 있습니다.
다음은 재귀적 질의를 사용해 access-configs 아래의 정보를 질의하는 명령어입니다.
curl -w "\n" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/access-configs/?recursive=true" -H "Metadata-Flavor: Google"
위와 같이 응답으로 access-configs/ 하위의 디렉토리인 externalIp와 type의 값을 반환하는 것을 확인할 수 있습니다.
응답을 더 보기 쉽게 변환하려면 요청에 "alt=text" 파라미터를 추가로 붙입니다.
3. 커스텀 메타데이터
위에서 소개한 메타데이터들은 모두 인스턴스나 프로젝트의 정보를 담은 데이터입니다.
인스턴스 생성 시에 이미 정해진 정보라는 말이죠.
하지만 GCP에서는 내가 원하는 키:값 쌍을 메타데이터 서버에 넣는 기능도 제공하고 있습니다.
이렇게 사용자가 넣은 메타데이터를 커스텀 메타데이터라고 합니다.
커스텀 메타데이터는 인스턴스 생성 시에, 혹은 이미 생성된 인스턴스의 수정을 통해 지정할 수 있습니다.
커스텀 메타데이터가 더 유용한 점은, 원하는 스크립트를 넣어서 시작 시에 실행하게 할 수 있다는 점입니다.
이렇게 커스텀 메타데이터를 통해 시작 시에 자동으로 실행되는 스크립트를 Startup script라고 합니다.
다음은 Startup script의 예시입니다.
커스텀 메타데이터의 Key에 startup-script를 적고 value에 다음 스크립트를 넣습니다.
#! /bin/bash
apt-get update
apt-get install -y apache2
cat <<EOF > /var/www/html/index.html
<html><body><h1>Hello World</h1>
<p>This page was created from a simple startup script!</p>
</body></html>
EOF
스크립트는 시작 시에 apache2 웹서버를 설치하고 특정 문구가 담긴 페이지로 수정합니다.
VM의 IP로 접근하면 다음과 같이 Startup script에 따라 수정된 화면을 볼 수 있습니다.
이렇게 커스텀 메타데이터를 활용해서 Startup sciprt를 통해 시작 시 스크립트를 구성할 수 있습니다.
4. 메타데이터, 안전할까?
이렇게 메타데이터 서버를 활용하는 방법에 대해 알아봤습니다.
보다시피 메타데이터는 인스턴스의 민감한 정보(서비스 어카운트, IAM 정책 등..)도 담고 있었는데요.
그런 메타데이터 서버를 암호화된 프로토콜인 HTTPS도 아닌 HTTP로 접근하면 보안적으로 문제가 없을까?? 라고 생각할 수 있습니다.
결과부터 말하면 메타데이터 서버는 안전하다 입니다.
우선 메타데이터 서버의 주소는 어디에서나 접근할 수 없습니다.
당장 로컬 환경의 브라우저에서 아래의 메타데이터서버 주소로 접근을 시도하면 아무 것도 뜨지 않습니다.
http://metadata.google.internal/computeMetadata/v1/
그 이유는 메타데이터 서버의 IP주소(169.254.169.254)가 라우터에 의해 라우팅되지 않는 169.254.0.0/16 범위 내의 주소이기 때문에, 오직 메타데이터 서버와 링크된 VM만 접속할 수 있는 것입니다. (이를 Link-local address 라고 합니다)
GCP document 또한 이런 보안적 불안함에 대한 답을 명시하고 있습니다.
위의 정보를 종합해보면, 혹시라도 VM과 메타데이터 서버 사이에서 중요한 정보를 스니핑하면 어떻하지? 라는 질문에 이와 같이 답할 수 있습니다.
VM과 메타데이터 사이에서 이동하는 정보는 절대 네트워크를 지나지 않는다.
5. 마치며
이렇게 메타데이터가 무엇인지, 부터 시작해서 메타데이터 서버의 보안적 안전함에 대해 말하는 것으로 이번 포스팅을 마무리지었습니다.
마지막에 메타데이터 서버의 안전함을 말했지만, 물론 역시 잠재적인 위협이 존재하는 것은 사실입니다.
실제로 VM 인스턴스 내의 프로세스는 별다른 인증 절차 없이 메타데이터를 조회할 수 있기 때문에 이를 이용한 공격 사례가 있다고도 합니다.
보안은 자연재해와 같이 항상 대비해야 하기 때문에, 조심해서 나쁠 것은 없다고 생각합니다.
이번 포스팅을 통해 메타데이터를 안전하게 활용할 수 있었으면 합니다.