Zettelkasten

GCP API 키의 androidKeyRestrictions 빈 객체는 제한이 없는 것과 같다

·수정 2026.05.14·수정 3

요약

  • GCP API 키에 androidKeyRestrictions: {} (빈 객체) 만 있으면 사실상 무제한 키
  • Firebase 자동 생성 키는 종종 이 상태로 남아 있고, 이름과 무관하게 모든 API를 호출 가능
  • 제한이 실제로 작동하려면 allowedApplications에 패키지명 + SHA-1 지문을 등록해야 함

본문

문제 상황

Firebase가 자동 생성한 키 (displayName: "Android key (auto created by Google Service)")의 설정을 점검하다 보면 다음과 같이 돼 있는 경우가 많다:

restrictions:
  androidKeyRestrictions: {}   # 빈 객체
  # apiTargets 없음 → 모든 API 호출 가능

콘솔 UI에서는 "Android 앱 제한"으로 표시되지만, 실제로는 어디서든 모든 GCP API를 호출 가능한 상태다.

빈 androidKeyRestrictions의 의미

형태 동작
androidKeyRestrictions 없음 제한 없음 (Unrestricted)
androidKeyRestrictions: {} (빈 객체) 제한 없음과 동일 (allowedApplications 비어있음)
androidKeyRestrictions: { allowedApplications: [...] } 등록된 패키지+SHA-1 만 허용

UI상 "Android apps" 라디오가 선택돼 있어도 allowedApplications가 비었으면 enforcement가 동작하지 않는다. 직관과 반대로 동작하는 함정.

Firebase 자동 생성 키의 위험성

Firebase 프로젝트를 만들면 SDK가 자동으로 API 키를 생성하는데:

  • 이름: "Android key", "Browser key", "Server key" 등
  • 제한: 종종 빈 객체 상태로 생성됨
  • 용도: Firebase Installations, Remote Config 등 클라이언트 SDK용
  • 문제: 키 자체는 모든 GCP API에 접근 가능 (Gemini, Firestore, Identity Toolkit 등)

→ 클라이언트 앱에 임베드된 키가 유출되면 Firebase 외 다른 API까지 악용 가능.

안전한 설정

최소 2가지 제한을 동시에 걸어야 함:

  1. API Target 제한 (필수):

    gcloud services api-keys update KEY_ID \
      --api-target=service=firebaseinstallations.googleapis.com \
      --api-target=service=firebaseremoteconfig.googleapis.com
    

    → 키가 호출할 수 있는 API 화이트리스트

  2. Application Restriction (Android의 경우 SHA-1):

    gcloud services api-keys update KEY_ID \
      --allowed-application=sha1_fingerprint=AA:BB:...,package_name=com.example.app
    

    → 어디서 호출되는지 검증

둘 중 하나만 걸면 부족:

  • Target만: 키 유출 시 허용된 API들은 여전히 외부에서 악용 가능
  • Application만: 우회 가능성(SDK 디컴파일로 SHA-1 위조 시도) + 다른 API 활성화돼있으면 다 노출

점검 방법

프로젝트의 모든 API 키 현황:

gcloud services api-keys list --project=PROJECT_ID --format="table(
  uid,
  displayName,
  restrictions.androidKeyRestrictions.allowedApplications.len(),
  restrictions.apiTargets.len(),
  createTime
)"

androidKeyRestrictions 또는 apiTargets가 비어있는 키는 즉시 점검 대상.

교훈

  1. "Android key"라는 이름만 보고 안심하면 안 됨 → 실제 제한 내용 확인 필수
  2. 빈 객체 {} 는 GCP에서 "제한 없음"의 시각적 위장
  3. 키 생성 자동화(Firebase auto-create)는 편의성과 보안의 트레이드오프
  4. 오래된 키는 정기 audit이 필요

관련 노트

참고