S3 퍼블릭 액세스 차단(Block Public Access)이 객체 공개 설정을 무력화하는 이유
S3에 이미지를 업로드하고 객체 ACL을 'public-read'로 설정했는데도 URL로 접근하면 'Access Denied'가 반환되는 상황은 AWS를 처음 다루는 엔지니어뿐 아니라 경험 있는 팀에서도 자주 마주치는 문제다. 원인은 대부분 하나다 — 버킷 수준의 'Block Public Access' 설정이 객체 ACL보다 상위에서 동작하기 때문이다.
TL;DR — S3 퍼블릭 액세스 차단 문제 요약
| 확인 항목 | 예상 상태 | 실제 차단 원인 |
|---|---|---|
| 객체 ACL | public-read 설정됨 | Block Public Access가 ACL을 무시함 |
| 버킷 Block Public Access | 기본값: 모두 활성화 | 4가지 설정 중 하나라도 켜져 있으면 퍼블릭 접근 차단 |
| 버킷 정책 | 없거나 Allow 없음 | ACL 없이 정책만으로 퍼블릭 접근 허용 가능 |
| 계정 수준 Block Public Access | 기본값: 모두 활성화 | 버킷 설정보다 상위에서 적용됨 |
S3 퍼블릭 액세스 제어 계층 구조 이해
S3의 접근 제어는 단일 설정이 아니라 여러 계층이 순서대로 평가되는 구조다. 객체 ACL을 'public-read'로 바꾸는 것은 가장 하위 계층을 건드리는 것이고, 그 위에 버킷 정책, 버킷 Block Public Access, 계정 수준 Block Public Access가 차례로 쌓여 있다. 상위 계층이 'Deny'를 내리면 하위 계층의 'Allow'는 효력이 없다.
AWS는 2018년 이후 신규 버킷 생성 시 Block Public Access 4가지 옵션을 모두 활성화한다. 이 기본값은 의도치 않은 데이터 노출을 막기 위한 것이지만, 퍼블릭 접근이 필요한 정적 웹사이트 호스팅이나 공개 이미지 서빙 시나리오에서는 직접 해제해야 한다.
- 요청 진입: 클라이언트가 S3 객체 URL로 GET 요청을 보낸다.
- 계정 수준 Block Public Access 평가: AWS Organizations 또는 계정 설정에서 퍼블릭 접근이 차단되어 있으면 즉시 Access Denied 반환. 버킷 설정을 볼 필요도 없다.
- 버킷 수준 Block Public Access 평가: 4가지 설정 중 관련 항목이 활성화되어 있으면 버킷 정책과 ACL을 무시하고 차단.
- 버킷 정책 평가: Explicit Deny가 있으면 차단. Allow가 있으면 허용.
- 객체 ACL 평가: 버킷 정책에 Allow가 없을 때 ACL이 평가된다. public-read ACL이 있으면 허용.
Block Public Access 4가지 설정의 정확한 의미
이 4가지를 구분하지 않으면 '일부만 해제'했을 때 왜 여전히 차단되는지 이해할 수 없다.
| 설정 이름 | 차단 대상 |
|---|---|
| BlockPublicAcls | 퍼블릭 ACL을 부여하는 PUT 요청 자체를 차단. 기존 ACL은 유지되지만 새로 설정 불가. |
| IgnorePublicAcls | 기존 퍼블릭 ACL을 무시. ACL이 public-read여도 퍼블릭 접근 불허. |
| BlockPublicPolicy | 퍼블릭 접근을 허용하는 버킷 정책 PUT 요청을 차단. |
| RestrictPublicBuckets | 퍼블릭 버킷 정책이 있어도 AWS 서비스 주체와 인증된 사용자 외 접근 차단. |
객체 ACL을 public-read로 설정했는데 접근이 안 된다면 IgnorePublicAcls가 활성화되어 있을 가능성이 높다. 이 설정은 ACL 자체를 무효화하기 때문에 ACL 값이 무엇이든 퍼블릭 접근이 불가능하다.
Block Public Access는 방화벽 앞단의 ACL 같은 개념이다. 방화벽이 포트를 막아두면 서버 내부에서 포트를 열어도 외부에서 접근할 수 없다. 객체 ACL을 바꾸는 것은 서버 내부 설정을 바꾸는 것이고, Block Public Access는 그 앞의 방화벽이다.
S3 퍼블릭 액세스 차단 문제 진단 — 단계별 CLI
Step 1. 계정 수준 Block Public Access 확인
버킷 설정을 보기 전에 계정 수준 설정을 먼저 확인해야 한다. 계정 수준에서 차단이 걸려 있으면 버킷 설정을 아무리 바꿔도 소용없다 — 이 계층을 건너뛰고 버킷만 수정하다가 시간을 낭비하는 경우가 많다.
aws s3control get-public-access-block \
--account-id 123456789012
응답에서 BlockPublicAcls, IgnorePublicAcls, BlockPublicPolicy, RestrictPublicBuckets 중 하나라도 true이면 계정 수준에서 차단 중이다.
Step 2. 버킷 수준 Block Public Access 확인
계정 수준이 문제없다면 버킷 수준을 확인한다. 버킷 수준 설정은 계정 설정을 상속하거나 독립적으로 구성할 수 있다.
aws s3api get-public-access-block \
--bucket your-bucket-name
4가지 항목 중 어떤 것이 활성화되어 있는지 정확히 파악한 뒤 해제 여부를 결정한다.
Step 3. 버킷 수준 Block Public Access 해제 (필요한 경우)
퍼블릭 접근이 실제로 필요한 버킷이라면 4가지를 모두 false로 설정한다. 운영 환경에서는 이 변경이 보안 정책에 부합하는지 반드시 검토해야 한다.
aws s3api put-public-access-block \
--bucket your-bucket-name \
--public-access-block-configuration \
'BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false'
Step 4. 객체 ACL 또는 버킷 정책으로 퍼블릭 접근 허용
Block Public Access를 해제한 뒤에도 실제 접근 허용 설정이 없으면 여전히 차단된다. ACL 방식과 버킷 정책 방식 중 하나를 선택한다.
방법 A: 객체 ACL로 퍼블릭 접근 허용
aws s3api put-object-acl \
--bucket your-bucket-name \
--key your-image.jpg \
--acl public-read
방법 B: 버킷 정책으로 퍼블릭 접근 허용 (권장)
버킷 정책 방식은 객체마다 ACL을 설정할 필요 없이 버킷 전체 또는 특정 경로에 대해 퍼블릭 접근을 허용할 수 있어 관리가 편하다.
🔽 버킷 정책 JSON 및 CLI 명령 (클릭하여 펼치기)
# policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
# 정책 적용
aws s3api put-bucket-policy \
--bucket your-bucket-name \
--policy file://policy.json
Step 5. 객체 URL로 직접 접근 테스트
설정 변경 후 실제 URL로 접근이 되는지 확인한다. curl을 사용하면 HTTP 상태 코드와 응답 헤더를 함께 볼 수 있어 디버깅에 유리하다.
curl -I https://your-bucket-name.s3.amazonaws.com/your-image.jpg
HTTP/1.1 200 OK가 반환되면 정상이다. 여전히 403이 반환된다면 Step 1부터 다시 확인한다.
실제 운영에서 마주친 패턴 — 잘못된 진단과 실제 원인
콘솔에서 객체를 선택하고 'Make public'을 클릭했는데 '이 버킷의 퍼블릭 액세스 차단 설정으로 인해 이 작업이 차단될 수 있습니다'라는 경고가 표시된 채로 진행한 경우가 있다. 작업은 성공한 것처럼 보이지만 실제로 ACL은 설정되지 않는다 — BlockPublicAcls=true이면 PUT Object ACL 요청 자체가 거부되기 때문이다.
처음에는 IAM 권한 문제로 오해하기 쉽다. s3:PutObjectAcl 권한이 있는데도 403이 반환되니 권한 설정을 반복해서 확인하게 된다. 하지만 실제 원인은 Block Public Access가 IAM 권한보다 먼저 요청을 차단하는 것이다.
이 상황에서 CloudTrail을 보면 PutObjectAcl 이벤트의 errorCode가 AccessDenied이고 errorMessage에 'bucket settings'가 언급된다. IAM 정책 시뮬레이터로는 이 차단을 재현할 수 없다 — Block Public Access는 IAM 평가 엔진 밖에서 동작하기 때문이다.
Block Public Access는 IAM Allow를 우회하는 별도의 제어 평면이다.
보안 고려사항 — 퍼블릭 버킷이 정말 필요한가
Block Public Access를 해제하기 전에 실제로 퍼블릭 접근이 필요한 시나리오인지 검토해야 한다. 많은 경우 아래 대안이 더 적합하다.
| 시나리오 | 권장 방식 |
|---|---|
| 인증된 사용자만 접근 | Presigned URL 사용 — 버킷은 비공개 유지 |
| CDN을 통한 공개 콘텐츠 서빙 | CloudFront + OAC(Origin Access Control) — 버킷은 비공개 유지 |
| 정적 웹사이트 호스팅 | 퍼블릭 버킷 정책 또는 CloudFront + OAC |
| 임시 파일 공유 | Presigned URL — 만료 시간 설정 가능 |
CloudFront + OAC 구성은 버킷을 완전히 비공개로 유지하면서 CDN을 통해 콘텐츠를 서빙할 수 있어 보안과 성능을 동시에 확보할 수 있다.
S3 퍼블릭 액세스 차단 설정 전체 흐름 정리
- 계정 Block Public Access 확인: 가장 먼저 확인. true이면 모든 하위 설정이 무의미하다.
- 버킷 Block Public Access 확인: 계정 수준이 false여도 버킷 수준이 true이면 차단된다.
- IgnorePublicAcls 확인: 이 설정이 true이면 객체 ACL public-read는 효력이 없다.
- 버킷 정책 또는 ACL로 접근 허용: Block Public Access 해제 후 명시적 Allow가 있어야 접근된다.
마무리 및 다음 단계
S3 퍼블릭 액세스 차단 문제는 계층 구조를 이해하면 빠르게 해결할 수 있다. 핵심은 객체 ACL 변경 전에 계정 및 버킷 수준의 Block Public Access 설정을 먼저 확인하는 것이다. 운영 환경에서는 버킷을 퍼블릭으로 열기보다 CloudFront + OAC 또는 Presigned URL을 검토하는 것이 보안 관점에서 더 적합하다.
- AWS 공식 문서: S3 Block Public Access
- AWS 공식 문서: Presigned URL
- AWS 공식 문서: CloudFront + S3 Origin Access Control
용어 정리 (Glossary)
| 용어 | 설명 |
|---|---|
| Block Public Access | S3 버킷 및 계정 수준에서 퍼블릭 접근을 차단하는 4가지 설정의 집합. ACL 및 버킷 정책보다 상위에서 동작한다. |
| ACL (Access Control List) | S3 객체 또는 버킷에 부여하는 접근 제어 목록. public-read는 모든 사용자에게 읽기 권한을 부여한다. |
| IgnorePublicAcls | Block Public Access 설정 중 하나. 활성화 시 퍼블릭 ACL이 설정되어 있어도 퍼블릭 접근을 허용하지 않는다. |
| Presigned URL | 특정 S3 객체에 대해 시간 제한이 있는 임시 접근 URL. 버킷을 퍼블릭으로 열지 않고 인증된 접근을 제공할 수 있다. |
| OAC (Origin Access Control) | CloudFront에서 S3 버킷에 접근할 때 사용하는 인증 메커니즘. 버킷을 비공개로 유지하면서 CDN 서빙이 가능하다. |
댓글
댓글 쓰기