Zettelkasten

GCP SA key의 사용 흔적은 private_key_id로 필터링한다

·수정 2026.05.14·수정 1

요약

  • GCP service account key의 실제 사용 흔적을 조사할 때는 SA email이 아닌 private_key_id로 필터링해야 정확하다.
  • 한 SA는 보통 여러 user-managed key를 보유하므로 email 필터는 다른 key 사용까지 포함해 특정 key의 영향 범위를 과대평가한다.
  • 단, Data Access 로그가 꺼져 있으면 데이터 read 활동은 보이지 않는다 — "흔적 없음 ≠ 사용 없음".

본문

필터 쿼리

protoPayload.authenticationInfo.serviceAccountKeyName=~"keys/<PRIVATE_KEY_ID>$"

serviceAccountKeyName 필드는 다음 형식이다:

projects/<PROJECT>/serviceAccounts/<EMAIL>/keys/<PRIVATE_KEY_ID>

정규식 $ 앵커로 끝부분만 매칭하면 key id 하나만으로 정확히 필터링된다.

실행 예시

# SA JSON 파일에서 private_key_id 추출
python3 -c "import json; print(json.load(open('sa.json'))['private_key_id'])"

# 해당 key의 90일 사용 흔적 조회
gcloud logging read \
  'protoPayload.authenticationInfo.serviceAccountKeyName=~"keys/<PRIVATE_KEY_ID>$"' \
  --project=<PROJECT> --freshness=90d --limit=500 \
  --format="value(timestamp,protoPayload.requestMetadata.callerIp,protoPayload.methodName)"

활용 시나리오

  • 키 회전 전 영향 분석: rotate 대상 key가 실제 어디서 쓰이는지 caller IP/UA 확인 후 안전하게 회전
  • dead key 식별: 같은 SA의 여러 user-managed key 중 미사용 key를 골라 선제적으로 정리
  • 사용처 audit: 특정 key id 기준으로 호출자 IP/UA 분포 확인 → 예상 외 호출처가 있는지 점검

가시성 한계

이 방법은 Admin Activity 로그 기반이다. 기본으로 켜져 있지만:

  • Data Access 로그는 기본 OFF (BigQuery, GCS, Firestore 등 데이터 read/write)
  • Cloud SQL 등 일부 서비스만 별도 활성화되어 있을 수 있음
  • 따라서 "해당 key로 BigQuery 테이블을 SELECT * 한 활동은 audit log에 안 남는다"
  • audit log 흔적 없음 ≠ 사용 없음

키 회전/감사 표준 절차:

  1. 의심 키 또는 회전 대상 key 비활성화/삭제
  2. Data Access 로그 활성화 (이후 추적 가능하도록)
  3. Admin Activity 흔적 확인 (이 노트의 방법)
  4. 서비스별 보조 로그로 보완 — BigQuery INFORMATION_SCHEMA.JOBS_BY_PROJECT, GCS access log, Firebase Auth 변경 이력 등

함께 보는 필드

필드 용도
protoPayload.authenticationInfo.principalEmail SA email (덜 정확)
protoPayload.authenticationInfo.serviceAccountKeyName full key path (정확)
protoPayload.requestMetadata.callerIp 호출자 IP
protoPayload.requestMetadata.callerSuppliedUserAgent UA
protoPayload.methodName 호출된 API 메서드

참고