본문으로 건너뛰기
aws검색
기초

IAM 정책과 평가 로직 (사용자, 역할, 정책 평가 순서)

IAM 사용자와 역할, 자격 증명 기반 정책과 리소스 기반 정책, 권한 경계와 세션 정책, SCP 와 RCP 가 한 요청에 어떤 순서로 적용되는지 그림으로 정리하고, 최소 권한을 만드는 실무 도구(Access Analyzer, IAM Policy Autopilot)를 소개합니다.

IAM정책 평가AssumeRole권한 경계Access Analyzer2026-10 기준, 약 9분

IAM 의 등장인물

IAM(Identity and Access Management)은 "누가(주체) 무엇을(액션) 어디에(리소스) 어떤 조건에서" 할 수 있는지를 정합니다. 모든 AWS API 호출은 IAM 평가를 거칩니다.

주체자격 증명언제 쓰나
루트 사용자이메일과 비밀번호계정 해지, 일부 결제 설정 같은 소수 작업만. 평소엔 잠가 둠
IAM 사용자장기 액세스 키, 비밀번호되도록 쓰지 않음. 외부 시스템이 키만 받을 수 있을 때 예외적으로
IAM 역할STS 가 주는 임시 자격 증명EC2, Lambda, ECS 태스크, 다른 계정, 외부 IdP 연동, 사람의 로그인
페더레이션 사용자IdP 토큰을 역할로 교환IAM Identity Center, SAML, OIDC(GitHub Actions 등)

팁 사람은 IAM Identity Center로, 워크로드는 역할로 들어오게 하면 장기 액세스 키가 거의 필요 없습니다. 키가 없으면 유출될 키도 없습니다.

정책의 종류

정책어디에 붙나하는 일
자격 증명 기반 정책사용자, 그룹, 역할주체가 할 수 있는 일을 허용
리소스 기반 정책S3 버킷, KMS 키, SQS, Lambda 등리소스에 누가 접근할 수 있는지 허용. 다른 계정 주체를 지정 가능
권한 경계 (permissions boundary)사용자, 역할자격 증명 정책이 줄 수 있는 최대치
세션 정책AssumeRole 호출 때 넘김그 세션에서만 더 좁힘
SCPOrganizations 의 OU, 계정계정 안 주체가 받을 수 있는 최대치
RCPOrganizations 의 OU, 계정계정 안 리소스에 허용될 수 있는 최대치

SCP 와 RCP 는 권한을 주지 않습니다. 상한선만 정합니다. SCP 에서 s3:* 를 허용해도 역할에 정책이 없으면 아무것도 못 합니다.

정책 평가 순서

한 요청이 들어오면 IAM 은 관련된 모든 정책을 모아 다음 순서로 판단합니다.

한 API 요청의 평가 순서 (같은 계정 기준) 1. 명시적 Deny? 모든 정책을 다 모아서 하나라도 맞으면 2. RCP, SCP 조직 상한선이 허용하는가 3. 허용 정책 리소스 기반 또는 자격 증명 기반이 허용 4. 경계와 세션 권한 경계, 세션 정책 범위 안인가 허용 (Allow) API 실행 거부 (AccessDenied) 1 에서 맞으면 명시적 거부, 2 부터 4 에서 막히거나 아무도 허용하지 않으면 암묵적 거부 예: 맞음 아니오 아무도 없음 범위 밖
IAM 정책 평가 흐름: 명시적 Deny 를 먼저 보고, 상한선 정책을 거친 뒤 허용 여부를 정함
  1. 어느 정책이든 명시적 Deny 가 맞으면 끝입니다. 거부.
  2. RCP 와 SCP 가 이 요청을 허용하지 않으면 거부. (관리 계정의 주체에는 SCP 가 적용되지 않습니다.)
  3. 같은 계정 안이면 리소스 기반 정책 또는 자격 증명 기반 정책 중 하나가 허용하면 다음 단계로 갑니다.
  4. 권한 경계와 세션 정책이 있으면 그 범위 안이어야 합니다.
  5. 아무것도 허용하지 않았다면 암묵적 거부입니다.

다른 계정의 리소스에 접근할 때는 조건이 더 엄격합니다. 호출하는 쪽의 자격 증명 정책과 리소스 쪽의 리소스 기반 정책이 둘 다 허용해야 합니다. 다른 계정 S3 에 쓸 때 버킷 정책만 열고 역할 정책을 빼먹어서 403 이 나는 일이 흔합니다. 자세한 추적법은 AccessDenied 트러블슈팅에 있습니다.

정책 문법 핵심

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadAppBucket",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:ListBucket"],
      "Resource": ["arn:aws:s3:::app-data-prod", "arn:aws:s3:::app-data-prod/*"],
      "Condition": { "StringEquals": { "aws:PrincipalOrgID": "o-abc123example" } }
    },
    {
      "Sid": "DenyWithoutTLS",
      "Effect": "Deny",
      "Action": "s3:*",
      "Resource": ["arn:aws:s3:::app-data-prod", "arn:aws:s3:::app-data-prod/*"],
      "Condition": { "Bool": { "aws:SecureTransport": "false" } }
    }
  ]
}
  • ListBucket 은 버킷 ARN, GetObject 는 버킷/* 객체 ARN 에 걸립니다. 둘을 섞으면 조용히 안 맞습니다.
  • 자주 쓰는 전역 조건 키: aws:PrincipalOrgID(우리 조직 주체만), aws:SourceVpce(특정 VPC 엔드포인트 경유만), aws:RequestedRegion(리전 제한), aws:PrincipalTag/...(ABAC), aws:SecureTransport.
  • NotAction, NotResource 는 Allow 와 함께 쓰면 생각보다 넓게 열립니다. Deny 와 짝지어 쓰는 것이 안전합니다.

역할 위임 (AssumeRole)

역할에는 두 개의 정책이 붙습니다. 신뢰 정책(누가 이 역할을 맡을 수 있나)과 권한 정책(맡은 뒤 무엇을 할 수 있나)입니다.

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Federated": "arn:aws:iam::111122223333:oidc-provider/token.actions.githubusercontent.com" },
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Condition": {
      "StringEquals": { "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" },
      "StringLike": { "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:ref:refs/heads/main" }
    }
  }]
}

GitHub Actions 같은 CI 는 이렇게 OIDC 로 역할을 맡게 하면 저장소에 액세스 키를 넣을 필요가 없습니다. sub 조건을 빼면 아무 저장소나 이 역할을 맡을 수 있으니 반드시 저장소와 브랜치까지 좁힙니다.

다른 회사(SaaS 벤더)에 역할을 내줄 때는 sts:ExternalId 조건으로 혼동된 대리인(confused deputy) 문제를 막습니다. 반대로 AWS 의 신원을 외부 서비스로 내보내야 할 때는 2025-11 에 나온 IAM 아웃바운드 아이덴티티 페더레이션으로 AWS 가 서명한 JWT 를 받아 외부 서비스에 제시할 수 있습니다.

최소 권한 만들기

처음부터 완벽한 최소 권한 정책을 쓰기는 어렵습니다. 넓게 시작해 좁히는 도구를 씁니다.

도구하는 일
IAM Access Analyzer 외부 접근 분석조직 밖에서 접근 가능한 버킷, 역할, 키를 찾음
Access Analyzer 미사용 접근 분석90 일 동안 안 쓴 역할, 키, 권한을 찾음 (유료)
Access Analyzer 정책 생성CloudTrail 기록으로 실제 쓴 액션만 담은 정책 초안 생성
정책 검증, 사용자 지정 정책 검사문법 오류, 너무 넓은 권한, 금지한 액션 포함 여부를 CI 에서 검사
마지막 액세스 정보서비스별로 마지막 사용 시각을 보여 줘서 안 쓰는 서비스 권한을 지움
IAM Policy Autopilotre:Invent 2025 에 공개된 오픈 소스 MCP 서버. 코드를 읽고 필요한 IAM 정책 초안을 만들어 줌

할당량과 숫자

  • 관리형 정책 문서 크기는 6,144 자, 역할 하나에 붙일 수 있는 관리형 정책은 기본 10 개(최대 20 개로 늘릴 수 있음)입니다.
  • 역할 세션의 최대 시간은 기본 1 시간이고 역할 설정에서 최대 12 시간까지 늘릴 수 있습니다. 역할 체이닝(역할로 다른 역할 맡기)은 1 시간이 한계입니다.
  • IAM 변경은 전 세계로 퍼지는 데 짧은 지연이 있습니다. 정책을 고친 직후의 AccessDenied 는 몇 초 뒤 다시 시도해 봅니다.

자주 하는 실수

  • "Resource": "*" 와 "Action": "*" 를 개발 편의로 붙이고 잊음. Access Analyzer 의 미사용 접근 결과를 주기적으로 봅니다.
  • 루트 액세스 키 생성. 만들 이유가 거의 없습니다. 조직 단위로는 루트 자격 증명 중앙 관리로 멤버 계정의 루트 비밀번호 자체를 없앨 수 있습니다.
  • 권한 경계를 위임 없이 씀. 경계는 "개발자가 스스로 역할을 만들되 정해진 범위를 넘지 못하게" 할 때 진가가 있습니다. iam:CreateRole 에 iam:PermissionsBoundary 조건을 걸어야 의미가 있습니다.
  • Deny 문에 aws:PrincipalArn 예외를 넣지 않음. 파이프라인 역할까지 막혀서 배포가 멈춥니다.

이 문서에서