오브젝트 스토리지와 S3 · 접근 제어(정책·프리사인드 URL) · 실습
사용자와 정책으로 접근 제어하기
목표
서비스 사용자를 만들고 최소 권한 정책을 직접 작성해 부착하면서, 권한 범위를 접두어 단위로 좁히는 습관을 만든다.
왜 중요한가
스토리지 유출 사고의 대부분은 복잡한 공격이 아니라 넓게 열어 둔 권한에서 옵니다. "이미지만 있으니까"라며 버킷을 익명 읽기로 열었는데, 몇 달 뒤 그 버킷 아래에 백업이나 사용자 업로드가 섞여 들어가는 식입니다. 정책의 Resource 를 버킷 전체(arn:aws:s3:::bucket/*)로 잡는 것도 같은 문제입니다 — 서비스 하나의 자격 증명이 새면 버킷 전체가 노출됩니다. 접두어까지 좁혀 두면 피해가 그 접두어 안에 갇힙니다. 그리고 이것은 구현 버그에 대한 방어이기도 합니다. MinIO 의 CVE-2025-62506 은 세션 정책 우회로 권한이 상승하는 취약점이었습니다. 정책을 좁게 쓰는 습관은 그런 순간에 남는 마지막 방어선입니다.
단계
1. mc admin user add local appuser appuser-secret-123 으로 사용자를 만들고 별칭 app 을 그 자격 증명으로 설정한다.
2. mc ls app/lab-media 를 시도하고 결과를 /root/pol/denied.txt 에 저장한다. 파일에 denied 또는 Access Denied 문자열이 있어야 한다.
3. /root/pol/readonly.json 에 정책을 쓴다. s3:GetObject 와 s3:ListBucket 을 허용하고 Resource 는 arn:aws:s3:::lab-media 와 arn:aws:s3:::lab-media/* 두 개다.
4. mc admin policy create local labreadonly /root/pol/readonly.json 후 mc admin policy attach local labreadonly --user appuser 를 실행한다. mc ls app/lab-media 가 성공해야 한다.
5. mc cp /opt/fixtures/s3/readme.txt app/lab-media/doc/nope.txt 가 실패해야 한다. /root/pol/write.txt 에 write_denied=true 를 적는다.
6. /root/pol/imgonly.json 에 Resource 를 arn:aws:s3:::lab-media/img/* 로 좁힌 정책을 쓰고 labimgonly 로 만들어 부착한다. app/lab-media/img/logo.png 조회는 되고 app/lab-media/doc/sales.csv 조회는 실패해야 한다. /root/pol/prefix.txt 에 img=ok doc=denied 를 적는다.
7. local/lab-media/public/ 접두어만 익명 다운로드로 연다. 익명 GET 이 public/ 아래 객체에는 200, private/ 아래 객체에는 403 이어야 한다. /root/pol/anon.txt 에 public=200 private=403 을 적는다.
참고
- 정책 목록:
mc admin policy list local - 부착 확인:
mc admin user info local appuser - 익명 공개:
mc anonymous set download local/lab-media/public - 흔한 실수 1:
ListBucket을 빼먹는 것 — 객체는 읽히는데 목록이 안 나옵니다. 둘은 다른 Action 이고 Resource 형식도 다릅니다. - 흔한 실수 2:
Resource를 버킷 전체로 잡는 것 — 자격 증명 하나가 새면 전부 노출됩니다.
단계 7개
- 서비스 사용자 만들기
- 정책 없는 사용자가 거부되는지 확인하기
- 읽기 전용 정책 작성하기
- 정책 부착하고 읽기 성공시키기
- 쓰기는 여전히 거부되는지 확인하기
- 접두어 한정 정책 만들기
- 특정 접두어만 익명 공개하기