User: arn:aws:iam::...:user/dev is not authorized to perform: s3:GetObject 같은 Access Denied는 클라우드 작업에서 가장 흔한 벽입니다. 당황해서 정책에 Allow를 마구 붙이면 보안만 망가집니다. IAM은 정해진 평가 순서가 있어서, 그 순서대로 좁혀가면 거의 항상 원인이 드러납니다.
핵심 원칙 — 평가 순서
IAM 권한 판정은 다음 규칙을 따릅니다. 하나라도 명시적 거부가 있으면 무조건 거부입니다.
| 단계 | 규칙 | 결과 |
|---|---|---|
| 1 | 명시적 Deny가 있나 | 있으면 즉시 거부 |
| 2 | 명시적 Allow가 있나 | 없으면 묵시적 거부 |
| 3 | 권한 경계(boundary)·SCP가 허용하나 | 막으면 거부 |
즉 "Allow가 있는데도 막힌다"면 어딘가에 명시적 Deny 또는 권한 경계/SCP 제한이 있다는 신호입니다. 또 자주 빠지는 함정은 리소스 정책입니다. S3 버킷 정책이나 KMS 키 정책이 사용자를 막으면, 사용자에게 Allow가 있어도 거부됩니다.
진단 — 도구로 원인 좁히기
추측 대신 정책 시뮬레이터로 어떤 정책이 결정에 작용했는지 봅니다.
로컬 터미널
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111122223333:user/dev \
--action-names s3:GetObject \
--resource-arns arn:aws:s3:::my-bucket/report.csv
출력의 EvalDecision이 explicitDeny인지 implicitDeny인지가 갈림길입니다. 추가로 CloudTrail에서 실패 이벤트를 보면 어떤 errorCode와 함께 거부됐는지 정확히 확인됩니다.
로컬 터미널
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetObject
체크 순서
- 오타·ARN 확인 — 액션 이름(
s3:GetObject), 리소스 ARN의 버킷·키, 와일드카드 범위를 먼저 봅니다. 의외로 절반은 여기서 끝납니다. - 묵시적 거부인가 — 시뮬레이터가
implicitDeny면 단순히Allow가 없는 것이니 최소 권한으로 추가합니다. - 명시적 거부 추적 —
explicitDeny면 사용자/그룹/역할 정책, 권한 경계, 조직 SCP를 차례로 뒤져Deny문장을 찾습니다. - 리소스 정책 확인 — 크로스 계정이거나 S3/KMS면 리소스 쪽 정책도 봅니다.
- 조건(Condition) 확인 —
aws:SourceIp,aws:MultiFactorAuthPresent같은 조건이 안 맞아 거부되는 경우가 많습니다. 사무실 밖에서 접근하니 막히는 식입니다.
요점 정리
- IAM은 명시적 Deny > Allow > 묵시적 Deny 순서로 평가됩니다.
simulate-principal-policy로explicitDeny인지implicitDeny인지부터 가릅니다.- Allow가 있는데도 막히면 권한 경계·SCP·리소스 정책·조건을 의심합니다.
- 정책을 늘리기 전에 ARN 오타와 조건부터 확인하는 게 빠릅니다.
IAM 정책을 직접 만들고 시뮬레이터로 권한을 검증해보려면 클라우드 트랙에서 회원가입 없이 무료로 시작할 수 있습니다.