GCS 퍼미션 오류 (403 Forbidden) 트러블슈팅 가이드

GCS(Google Cloud Storage)에서 발생하는 403 Forbidden 오류는 요청을 보낸 주체가 해당 버킷 또는 객체에 접근할 권한이 없음을 의미합니다.

이 오류는 주로 IAM(Identity and Access Management) 정책, ACL(Access Control List), 그리고 균일 버킷 수준 액세스(Uniform Bucket-Level Access) 설정 간의 충돌이나 불일치 때문입니다. IAM 정책은 Google Cloud 전체에서 사용되는 중앙 집중식 권한 관리 시스템으로, 역할(role) 기반으로 권한을 부여합니다. 예를 들어, ‘storage.objects.get’ 권한이 없으면 객체를 읽을 수 없어 403 오류가 발생할 수 있습니다. 반면 ACL은 레거시 접근 제어 방식으로, 버킷이나 개별 객체 수준에서 세밀한 권한을 설정할 수 있지만, IAM과 병행 사용 시 충돌이 생길 수 있습니다. Uniform Bucket-Level Access는 버킷 전체에 균일한 IAM 기반 액세스를 강제하는 기능으로, ACL을 무시하고 IAM만 적용되도록 하여 보안을 강화하지만, 기존 ACL 설정이 있는 경우 전환 과정에서 오류를 유발할 수 있습니다. 이러한 메커니즘 간 상호 작용이 제대로 조정되지 않으면, 예기치 않은 권한 거부가 발생하며, 이는 프로젝트 스코프 오류, 자격 증명 불일치, 또는 조직 수준의 Deny 정책으로 인해 더욱 복잡해질 수 있습니다.

403 오류를 진단하고 해결하기 위해서는 이 세 가지 권한 관리 메커니즘을 체계적으로 점검해야 합니다.

아래에서 좀 더 자세히 살펴보겠습니다.


1. 403 오류 진단: 권한 충돌의 세 가지 원인

GCS의 403 오류는 다음 세 가지 권한 시스템 중 하나 이상에서 접근이 명시적으로 거부되었거나, 혹은 허용 규칙이 누락되었을 때 발생합니다.

1.1. IAM 정책 누락/오류 (가장 흔한 원인)

IAM(Identity and Access Management) 정책은 GCP 프로젝트 및 리소스 전반에 걸쳐 누가 어떤 역할을 수행할 수 있는지를 정의하는 주된 권한 관리 방법입니다.

  • 원인: 요청 주체(사용자 계정, 서비스 계정)에게 해당 버킷에 대한 최소한의 역할(예: Storage Object Viewer 또는 Storage Object Creator)이 부여되지 않은 경우입니다.
  • IAM Policy 진단:
    • 요청 주체의 서비스 계정 또는 사용자 계정이 정확한 프로젝트 또는 버킷 수준에서 필요한 권한을 가지고 있는지 확인합니다.
    • 일반적으로 객체 읽기에는 storage.objectViewer 역할, 쓰기에는 storage.objectAdmin 역할이 필요합니다.

1.2. ACL(Access Control List) 불일치 (레거시 문제)

ACL은 객체 개별 단위로 접근 권한을 관리하는 레거시(Legacy) 시스템입니다. 균일 버킷 수준 액세스가 비활성화된 버킷에서 사용됩니다.

  • 원인: 버킷이나 객체의 ACL에 요청 주체가 포함되지 않았거나, ACL이 IAM 정책보다 더 제한적인 규칙을 가지고 있는 경우입니다. ACL은 IAM과 별도로 작동하기 때문에 혼란을 야기할 수 있습니다.
  • ACL 진단:
    • 버킷 설정에서 ‘액세스 제어(Access Control)’가 ‘세분화된(Fine-grained)’ (ACL 활성화)으로 설정되어 있는지 확인합니다.
    • 접근하려는 객체 또는 버킷의 ACL에 요청 주체(예: user-email@gserviceaccount.com)가 READER 또는 WRITER 권한을 가지고 있는지 확인합니다.

1.3. Uniform Bucket-Level Access (균일 액세스) 충돌

이 설정은 버킷 내의 모든 객체에 대해 ACL 사용을 완전히 비활성화하고, IAM 정책만을 유일한 권한 제어 수단으로 사용하도록 강제하는 기능입니다.

  • 원인: 버킷이 균일(Uniform) 액세스로 설정되어 있는데, 요청 주체가 ACL에만 의존하는 방식으로 접근을 시도하거나, ACL로만 권한을 부여받은 경우입니다. 균일 액세스가 활성화되면 모든 기존 ACL은 무시됩니다.
  • 진단:
    • 버킷의 ‘권한(Permissions)’ 탭에서 ‘액세스 제어’가 ‘균일’로 설정되어 있는지 확인합니다.
    • 균일 액세스가 활성화된 경우, 반드시 IAM 정책만을 점검해야 하며, ACL 기반의 요청(예: 오래된 라이브러리)은 실패합니다.

2. 실전 트러블슈팅 순서 체크리스트

403 오류 발생 시, 다음의 순서대로 점검하면 문제의 원인을 가장 빠르게 격리할 수 있습니다.

1단계: 균일 액세스 설정 확인 (권한 모델 결정)

  1. 버킷의 ‘권한’ 탭에서 균일 버킷 수준 액세스활성화되어 있는지 확인합니다.
  2. 활성화된 경우 (Uniform): ACL은 무시되므로, 다음 단계(IAM)만 점검합니다.
  3. 비활성화된 경우 (Fine-Grained/ACL): ACL과 IAM 정책을 모두 점검해야 합니다.

2단계: IAM 정책 (Principal 및 Role) 확인

  1. 요청 주체 확인: 403 오류를 받은 주체가 어떤 서비스 계정 ARN 또는 어떤 사용자 이메일인지 정확히 파악합니다.
  2. 역할 부여 확인:버킷 수준 또는 해당 버킷이 속한 프로젝트 수준에서 1단계의 주체에게 필요한 storage.objectViewer, storage.objectCreator 등의 역할이 부여되어 있는지 확인합니다.
    • 팁: IAM Role Binding에 오타가 있거나, 주체가 올바른 프로젝트/조직의 멤버인지 확인합니다.
  3. 조건부 IAM 확인: IAM 정책에 조건(Condition)이 설정되어 있어 특정 IP, 시간, 또는 요청 타입에서만 허용되는지 확인합니다.

3단계: ACL (비균일 액세스 시) 점검

  1. 객체 단위 확인: 만약 특정 객체에만 오류가 발생한다면, 해당 객체의 상세 정보에서 ACL 권한 목록을 확인합니다.
  2. 요청 주체가 READER 또는 WRITER 권한을 명시적으로 가지고 있는지 확인합니다.
  3. 기본 ACL 확인: 새로 업로드된 객체의 경우, 버킷의 기본 객체 ACL 설정이 요청 주체에게 접근 권한을 부여하는지 확인합니다.

3. 고급 진단: Cloud Audit Logs 활용

가장 확실한 진단 방법은 Cloud Audit Logs를 분석하는 것입니다.

  • 로그 활성화: GCP Console에서 ‘로깅(Logging)’ -> ‘로그 탐색기(Logs Explorer)’로 이동합니다.
  • 필터링: resource.type="gcs_bucket"protoPayload.status.code="403"으로 필터링합니다.
  • permissionDenied 확인: 로그 상세 내용에서 status.details 또는 status.message 필드를 확인합니다. 이 메시지에는 보통 “Caller does not have permission storage.objects.get on resource [Bucket/Object ARN]"과 같이 누락된 정확한 권한이 명시되어 있습니다. 이 정보를 토대로 IAM Role을 즉시 수정할 수 있습니다.

Disclaimer: 본 블로그의 정보는 개인의 단순 참고 및 기록용으로 작성된 것이며, 개인적인 조사와 생각을 담은 내용이기에 오류가 있거나 편향된 내용이 있을 수 있습니다.