用用户与策略控制访问
한국어 원문으로 표시합니다.
목표
서비스 사용자를 만들고 최소 권한 정책을 직접 작성해 부착하면서, 권한 범위를 접두어 단위로 좁히는 습관을 만든다.
왜 중요한가
스토리지 유출 사고의 대부분은 복잡한 공격이 아니라 넓게 열어 둔 권한에서 옵니다. "이미지만 있으니까"라며 버킷을 익명 읽기로 열었는데, 몇 달 뒤 그 버킷 아래에 백업이나 사용자 업로드가 섞여 들어가는 식입니다. 정책의 Resource 를 버킷 전체(arn:aws:s3:::bucket/*)로 잡는 것도 같은 문제입니다 — 서비스 하나의 자격 증명이 새면 버킷 전체가 노출됩니다. 접두어까지 좁혀 두면 피해가 그 접두어 안에 갇힙니다. 그리고 이것은 구현 버그에 대한 방어이기도 합니다. MinIO 의 CVE-2025-62506 은 세션 정책 우회로 권한이 상승하는 취약점이었습니다. 정책을 좁게 쓰는 습관은 그런 순간에 남는 마지막 방어선입니다.
단계
mc admin user add local appuser appuser-secret-123으로 사용자를 만들고 별칭app을 그 자격 증명으로 설정한다.mc ls app/lab-media를 시도하고 결과를/root/pol/denied.txt에 저장한다. 파일에denied또는Access Denied문자열이 있어야 한다./root/pol/readonly.json에 정책을 쓴다.s3:GetObject와s3:ListBucket을 허용하고Resource는arn:aws:s3:::lab-media와arn:aws:s3:::lab-media/*두 개다.mc admin policy create local labreadonly /root/pol/readonly.json후mc admin policy attach local labreadonly --user appuser를 실행한다.mc ls app/lab-media가 성공해야 한다.mc cp /opt/fixtures/s3/readme.txt app/lab-media/doc/nope.txt가 실패해야 한다./root/pol/write.txt에write_denied=true를 적는다./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를 적는다.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를 버킷 전체로 잡는 것 — 자격 증명 하나가 새면 전부 노출됩니다.
서비스 사용자 만들기
mc admin user add local appuser appuser-secret-123 으로 사용자를 만들고 별칭 app 을 그 자격 증명으로 설정한다.
관리자 별칭으로 사용자를 추가합니다. 액세스 키와 시크릿 키를 정해 주세요.
정책 없는 사용자가 거부되는지 확인하기
mc ls app/lab-media 를 시도하고 결과를 /root/pol/denied.txt 에 저장한다. 파일에 denied 또는 Access Denied 문자열이 있어야 한다.
새 별칭으로 목록을 시도하면 거부됩니다. 기본은 아무 권한도 없는 것입니다.
읽기 전용 정책 작성하기
/root/pol/readonly.json 에 정책을 쓴다. s3:GetObject 와 s3:ListBucket 을 허용하고 Resource 는 arn:aws:s3:::lab-media 와 arn:aws:s3:::lab-media/* 두 개다.
JSON 으로 Effect, Action, Resource 를 적습니다. 목록 조회와 객체 읽기는 서로 다른 Action 입니다.
정책 부착하고 읽기 성공시키기
mc admin policy create local labreadonly /root/pol/readonly.json 후 mc admin policy attach local labreadonly --user appuser 를 실행한다. mc ls app/lab-media 가 성공해야 한다.
정책을 만들고 사용자에게 붙이는 것은 별도 단계입니다.
쓰기는 여전히 거부되는지 확인하기
mc cp /opt/fixtures/s3/readme.txt app/lab-media/doc/nope.txt 가 실패해야 한다. /root/pol/write.txt 에 write_denied=true 를 적는다.
읽기 전용 정책이라면 업로드가 실패해야 합니다. 실패하는 것이 정상입니다.
접두어 한정 정책 만들기
/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 를 적는다.
Resource 에 와일드카드를 접두어까지 붙입니다. img/ 는 되고 doc/ 는 안 되게 하세요.
특정 접두어만 익명 공개하기
local/lab-media/public/ 접두어만 익명 다운로드로 연다. 익명 GET 이 public/ 아래 객체에는 200, private/ 아래 객체에는 403 이어야 한다. /root/pol/anon.txt 에 public=200 private=403 을 적는다.
버킷 전체를 여는 것과 접두어 하나만 여는 것은 사고 규모가 다릅니다.
명령 끝의 슬래시 한 글자를 조심하세요. 이 실습의 요지가 거기에 다 들어 있습니다.
mc anonymous set download local/lab-media/public → Resource: lab-media/public*
mc anonymous set download local/lab-media/public/ → Resource: lab-media/public/*
S3 에 폴더는 없습니다. 정책이 보는 것은 문자열 접두어뿐이라, 슬래시를 빠뜨리면 public-backup.tar 처럼 public 으로 시작하기만 하는 루트 객체까지 함께 열립니다. mc anonymous get-json 으로 서버에 실제로 걸린 Resource 를 확인하세요.
규칙은 걸 때마다 덧붙습니다. 같은 버킷에 두 번 걸면 public* 과 public/* 이 함께 남으니, 범위를 바꿀 때는 mc anonymous set none 으로 먼저 지우고 다시 거세요.