목록으로 가기

AWS IAM 유저, 역할, 정책 — 최소 권한 원칙과 크로스 계정 접근

IAM User와 Role 차이, Policy 작성법, STS로 임시 자격 증명 받기, 크로스 계정 접근까지 정리했습니다.

AWS IAM 유저, 역할, 정책 — 최소 권한 원칙과 크로스 계정 접근 ko posts aws IAM User와 Role 차이, Policy 작성법, STS로 임시 자격 증명 받기, 크로스 계정 접근까지 정리했습니다.

개요

IAM(Identity and Access Management)은 “누가 AWS에서 무엇을 할 수 있는가"를 제어하는 서비스입니다. EC2 하나 만들려고 해도 IAM 권한이 없으면 불가능합니다.

잘못 설정하면 보안 사고로 이어지고, 너무 빡빡하면 개발이 안 됩니다. 이 글은 IAM의 핵심 구성요소와 설계 원칙을 정리합니다.

1. IAM 구성 요소

상세 내용

4가지 핵심

구성요소 설명
User 사람에 해당하는 자격 증명 (개발자, 운영자)
Group User 묶음. 그룹에 붙인 정책이 소속 User 전부에 적용됨
Role 서비스나 외부 주체가 임시로 맡아 쓰는 권한
Policy 권한 규칙을 정의한 JSON 문서

관계

Policy (권한 정의)
  ├── 붙이는 대상: User
  ├── 붙이는 대상: Group (→ 안에 있는 User 전부 적용)
  └── 붙이는 대상: Role (→ 이 Role을 맡은 주체에 적용)

User vs Role 차이

User Role
누가 쓰냐 사람 서비스(EC2, Lambda), 외부 계정, CI/CD
인증 방식 Access Key or 콘솔 비밀번호 STS로 임시 자격증명 발급
영구성 영구 임시 (세션 만료)
권장 최소화 (사람만) 서비스 간 통신은 전부 Role
# 유저 생성
aws iam create-user --user-name developer-a

# 그룹에 추가
aws iam add-user-to-group --user-name developer-a --group-name developers

# Role 목록
aws iam list-roles

2. Policy (정책) 작성법

상세 내용

Policy = JSON으로 된 권한 규칙

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-bucket/*"
    },
    {
      "Effect": "Deny",
      "Action": "s3:DeleteObject",
      "Resource": "*"
    }
  ]
}

Statement 구성요소

의미 예시
Effect 허용/거부 Allow, Deny
Action 어떤 동작 s3:GetObject, ec2:RunInstances
Resource 어떤 리소스에 대해 arn:aws:s3:::my-bucket/*
Condition 조건 (선택) 특정 IP에서만, MFA 인증 시만

Allow와 Deny가 같이 있으면 뭐가 이기냐

공식 문서의 정책 평가 로직은 이렇습니다. 요청은 기본적으로 거부(암시적 거부)되고, 적용되는 정책 어딘가에 명시적 Deny가 하나라도 있으면 최종 결과는 Deny입니다. 명시적 Deny가 없고 Allow가 있을 때만 허용됩니다. 위 예시에서 s3:DeleteObject는 다른 정책이 아무리 허용해도 막힙니다.

Policy 종류

종류 설명
AWS Managed AWS가 미리 만들어둔 것 (ReadOnlyAccess 등)
Customer Managed 직접 만든 커스텀 정책
Inline 특정 User/Role에 직접 붙인 것 (비추, 관리 어려움)

대표적인 AWS Managed Policy

정책 권한
AdministratorAccess 전체 관리자 (모든 것 가능)
ReadOnlyAccess 읽기만 (변경 불가)
AmazonEC2FullAccess EC2 전체 권한
AmazonS3ReadOnlyAccess S3 읽기만
AmazonEKSClusterPolicy EKS 클러스터 관리
# 정책 붙이기 (User에)
aws iam attach-user-policy --user-name developer-a --policy-arn arn:aws:iam::aws:policy/ReadOnlyAccess

# 정책 붙이기 (Role에)
aws iam attach-role-policy --role-name app-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

3. Role과 AssumeRole

상세 내용

Role = “이 권한을 빌려 쓸 수 있게 해줄게”

EC2가 S3에 접근해야 할 때, Access Key를 EC2에 넣는 게 아니라 Role을 붙입니다. Role은 임시 자격증명을 발급받아서 사용합니다.

Trust Policy = “누가 이 Role을 맡을 수 있냐”

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

이 Trust Policy는 “EC2 서비스가 이 Role을 맡을 수 있다"는 뜻.

사용 예시들

시나리오 Principal 설명
EC2가 S3 접근 ec2.amazonaws.com Instance Profile로 연결
Lambda가 DynamoDB 접근 lambda.amazonaws.com Lambda 실행 역할
다른 AWS 계정에서 접근 arn:aws:iam::111111111111:root 크로스 계정
GitHub Actions에서 접근 OIDC Provider 키 없이 인증

AssumeRole (수동으로 Role 전환)

# 임시 자격증명 발급
aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/deploy-role \
  --role-session-name my-session

# 반환된 값으로 환경변수 설정
export AWS_ACCESS_KEY_ID="임시키"
export AWS_SECRET_ACCESS_KEY="임시시크릿"
export AWS_SESSION_TOKEN="임시토큰"

이렇게 하면 다른 계정의 Role 권한으로 작업 가능 (크로스 계정).

4. 최소 권한 원칙

상세 내용

“필요한 것만, 필요한 리소스에만, 필요한 시간만”

원칙 예시
Action 최소화 s3:* 대신 s3:GetObject, s3:PutObject
Resource 최소화 * 대신 arn:aws:s3:::my-bucket/*
Condition 활용 특정 IP, MFA 인증 시만 허용
임시 자격증명 사용 Access Key 대신 Role (자동 만료)

Condition 예시 — MFA 없으면 차단

{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
    "BoolIfExists": {
      "aws:MultiFactorAuthPresent": "false"
    }
  }
}

Condition 예시 — 특정 IP에서만 허용

{
  "Condition": {
    "IpAddress": {
      "aws:SourceIp": "203.0.113.0/24"
    }
  }
}

확인 도구

# 내가 지금 어떤 권한이 있는지
aws iam get-user
aws sts get-caller-identity

# 특정 동작 가능한지 시뮬레이션
aws iam simulate-principal-policy \
  --policy-source-arn arn:aws:iam::111111111111:user/developer-a \
  --action-names s3:GetObject

5. IAM 설계 패턴

상세 내용

팀/역할 기반 구조

Groups:
├── admins          → AdministratorAccess
├── developers      → 개발에 필요한 권한 (EC2, S3, CloudWatch 읽기)
├── devops          → 배포 권한 (EKS, ECR, CodePipeline)
└── readonly        → ReadOnlyAccess

Users:
├── admin-kim    → admins 그룹
├── dev-park     → developers 그룹
└── devops-lee   → devops 그룹

서비스별 Role

Roles:
├── ec2-app-role         → S3 읽기 + CloudWatch 쓰기
├── lambda-processor     → DynamoDB 읽기/쓰기 + SQS
├── eks-node-role        → ECR pull + CloudWatch
└── ci-deploy-role       → ECR push + EKS 배포

권한 경계 (Permission Boundary)

“이 유저가 아무리 정책을 붙여도 이 범위를 넘을 수 없다"는 상한선.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:*", "ec2:*", "cloudwatch:*"],
      "Resource": "*"
    }
  ]
}

개발자가 스스로 정책을 만들어도, Permission Boundary 안에서만 가능합니다. IAM 자체 권한 남용 방지.

6. 크로스 계정 접근

상세 내용

계정 A에서 계정 B의 리소스에 접근하기

계정 A (개발) → AssumeRole → 계정 B (운영)의 deploy-role → S3, EKS 접근

계정 B에서 Role 생성 (Trust Policy에 A 계정 허용)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

계정 A에서 사용

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/deploy-role \
  --role-session-name cross-account

이 패턴은 멀티 계정 환경에서 필수입니다. 계정마다 유저를 만드는 게 아니라, 하나의 계정에서 Role 전환으로 다른 계정에 접근합니다.

정책 평가에서는 Allow를 여러 개 붙여도 명시적 Deny 하나가 있으면 전부 막힙니다. 명시적 Deny가 다른 모든 Allow보다 우선합니다.

관련 포스트

EC2, ECS, EKS 차이점과 Auto Scaling, Fargate 구성 방법 EC2 인스턴스 타입 선택부터 Auto Scaling Group, ECS vs EKS 비교, Fargate …