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단계: 균일 액세스 설정 확인 (권한 모델 결정)
- 버킷의 ‘권한’ 탭에서 균일 버킷 수준 액세스가 활성화되어 있는지 확인합니다.
- 활성화된 경우 (Uniform): ACL은 무시되므로, 다음 단계(IAM)만 점검합니다.
- 비활성화된 경우 (Fine-Grained/ACL): ACL과 IAM 정책을 모두 점검해야 합니다.
2단계: IAM 정책 (Principal 및 Role) 확인
- 요청 주체 확인: 403 오류를 받은 주체가 어떤 서비스 계정 ARN 또는 어떤 사용자 이메일인지 정확히 파악합니다.
- 역할 부여 확인:버킷 수준 또는 해당 버킷이 속한 프로젝트 수준에서 1단계의 주체에게 필요한
storage.objectViewer,storage.objectCreator등의 역할이 부여되어 있는지 확인합니다.- 팁: IAM Role Binding에 오타가 있거나, 주체가 올바른 프로젝트/조직의 멤버인지 확인합니다.
- 조건부 IAM 확인: IAM 정책에 조건(Condition)이 설정되어 있어 특정 IP, 시간, 또는 요청 타입에서만 허용되는지 확인합니다.
3단계: ACL (비균일 액세스 시) 점검
- 객체 단위 확인: 만약 특정 객체에만 오류가 발생한다면, 해당 객체의 상세 정보에서 ACL 권한 목록을 확인합니다.
- 요청 주체가 READER 또는 WRITER 권한을 명시적으로 가지고 있는지 확인합니다.
- 기본 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 permissionstorage.objects.geton resource[Bucket/Object ARN]"과 같이 누락된 정확한 권한이 명시되어 있습니다. 이 정보를 토대로 IAM Role을 즉시 수정할 수 있습니다.
Disclaimer: 본 블로그의 정보는 개인의 단순 참고 및 기록용으로 작성된 것이며, 개인적인 조사와 생각을 담은 내용이기에 오류가 있거나 편향된 내용이 있을 수 있습니다.