AWS 기초 #2 IAM: 사용자, 그룹, 역할, 정책

10 분 소요

#1 AWS 입문의 마지막에서 “루트 사용자로 일하지 말자"라고 했습니다. 그러면 누구로 일해야 합니까? 답은 **IAM (Identity and Access Management)**으로 만든 사용자 / 역할입니다.

IAM은 글로벌 서비스입니다. 어느 리전에서 콘솔을 열어도 같은 사용자 / 역할 / 정책이 보입니다. 그리고 무료입니다. 추가 비용 없이 무한정 사용자를 만들 수 있습니다. 그래서 AWS에 처음 들어오면 가장 먼저 만나야 하는 서비스입니다.

이 글에서는 IAM의 4가지 요소를 한 번에 정리하고, 운영 권한 설계의 핵심 패턴까지 살펴보겠습니다.

큰 그림: IAM의 4가지 요소 #

요소무엇누가 / 무엇이 쓰는가
User (사용자)사람 한 명 또는 머신 한 대에 묶인 영구 자격콘솔 로그인, 액세스 키
Group (그룹)사용자 묶음그룹에 정책 붙이면 안의 사용자 모두 적용
Role (역할)“임시로 빌려 쓰는” 자격EC2, Lambda, 다른 계정의 사용자 등
Policy (정책)“무엇을 허용 / 거부할지” 의 JSON 문서위 셋에 붙어 권한을 정의

핵심은 정책이 곧 권한이라는 점입니다. 사용자 / 그룹 / 역할은 권한을 담는 그릇이고, 그 안의 정책이 진짜 무엇을 할 수 있는지 결정합니다.

Policy: JSON으로 권한 적기 #

먼저 정책부터 봅니다. 정책은 JSON 문서입니다. 이 모양에 익숙해지는 것이 IAM 학습의 80%입니다.

가장 단순한 정책
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

읽으면 s3:GetObject 액션을 my-bucket의 모든 객체 (*)에 대해 허용한다는 뜻입니다.

각 키의 의미:

무엇
Version정책 문법 버전. 항상 2012-10-17
Statement권한 규칙의 배열
EffectAllow 또는 Deny
Action어떤 API 호출을 허용 / 거부. <서비스>:<액션>
Resource어떤 리소스에. ARN으로
Condition (옵션)추가 조건. IP, 시간, 태그 등

Action의 형식 #

s3:GetObject처럼 <서비스>:<액션>입니다. 와일드카드도 됩니다.

Action 와일드카드 예
"Action": "s3:Get*"          // s3의 모든 Get 액션
"Action": "s3:*"             // s3의 모든 액션
"Action": ["s3:GetObject", "s3:PutObject"]  // 배열로 여러 

Resource의 형식 #

ARN으로 적습니다. ARN의 모양은 #1에서 봤습니다.

Resource 예
"Resource": "arn:aws:s3:::my-bucket"           // 버킷 자체
"Resource": "arn:aws:s3:::my-bucket/*"         // 버킷 안의 모든 객체
"Resource": "arn:aws:s3:::my-bucket/uploads/*" // 특정 prefix만
"Resource": "*"                                // 모든 리소스 (위험!)

Condition: 가장 강력한 제어 수단 #

조건이 정책의 진짜 힘을 만드는 부분입니다.

회사 IP에서만 허용
{
  "Effect": "Allow",
  "Action": "s3:*",
  "Resource": "arn:aws:s3:::my-bucket/*",
  "Condition": {
    "IpAddress": {
      "aws:SourceIp": ["203.0.113.0/24"]
    }
  }
}
MFA가 켜진 세션에서만 허용
{
  "Effect": "Allow",
  "Action": "iam:*",
  "Resource": "*",
  "Condition": {
    "Bool": { "aws:MultiFactorAuthPresent": "true" }
  }
}

자주 쓰는 조건 키:

무엇
aws:SourceIp요청 IP
aws:MultiFactorAuthPresentMFA 사용 여부
aws:RequestTag/<key>만들 때 태그
aws:ResourceTag/<key>리소스 태그
aws:CurrentTime시간

Allow / Deny 평가 순서 #

여러 정책이 겹치면 IAM은 다음 순서로 결정합니다.

평가 순서
1) 명시적 Deny가 하나라도 있으면 → 거부 (끝)
2) 명시적 Allow가 하나라도 있으면 → 허용
3) 둘 다 없으면 → 거부 (기본)

Deny가 항상 이깁니다. 그래서 “이 사용자는 prod 리소스만은 절대 못 만지게” 같은 가드레일은 Deny로 적습니다. 허용 정책 옆에 Deny를 함께 붙이는 패턴입니다.

User: 사람 / 머신을 위한 영구 자격 #

IAM 사용자는 이메일이 아닌 별도의 ID입니다. 콘솔 로그인 URL도 따로 생깁니다.

IAM 사용자 콘솔 URL
https://<계정ID>.signin.aws.amazon.com/console
또는
https://<계정 별칭>.signin.aws.amazon.com/console

사용자 만들기 #

콘솔에서 IAM → Users → Add users.

항목무엇
사용자 이름이메일이 아님. curtis, dev-bot 같은 식별자
콘솔 액세스비밀번호. 사람용
프로그래밍 액세스액세스 키. CLI / SDK 용 (#4)
권한그룹에 추가, 정책 직접 첨부, 또는 다른 사용자에서 복사

모범 사례: 사용자에 정책을 직접 붙이지 말고 그룹을 통해서 붙이세요. 이유는 다음 절에서 설명합니다.

액세스 키: 사용자가 가진 가장 위험한 자격 증명 #

액세스 키는 두 줄짜리 문자열입니다.

액세스 키의 모양
Access Key ID:     AKIAIOSFODNN7EXAMPLE
Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

이 둘을 가진 누구나 그 사용자의 모든 권한을 행사할 수 있습니다. 그래서:

  • 사용자 한 명당 액세스 키는 최대 2개 (회전 중 잠시 둘이 공존)
  • 절대 git / 코드에 넣지 말 것 (#1 함정 #2 사례)
  • 90일마다 회전 (#6에서 자세히)
  • 가능하면 사용자 액세스 키 대신 역할 (Role) 사용

Group: 사용자 관리의 단위 #

그룹은 사용자를 묶는 단위입니다. 그룹에 정책을 붙이면 그 그룹의 모든 사용자에게 자동으로 적용됩니다.

그룹 설계의 흔한 모양
Admins         → AdministratorAccess
Developers     → PowerUserAccess + (IAM 거부 정책)
ReadOnly       → ReadOnlyAccess
Billing        → 결제 콘솔 접근만

왜 사용자에 직접 붙이지 말고 그룹에? #

새 개발자가 입사했다고 상상해 봅시다.

사용자 직접 모델:

  • 기존 개발자 한 명을 골라 정책 목록을 따라 붙입니다.
  • “어, 저 사람한테 일주일 전에 추가한 정책이 뭐였지?” 하다가 누락하기 쉽습니다.
  • 시간이 지나면 개발자마다 권한이 미묘하게 달라집니다.

그룹 모델:

  • Developers 그룹에 추가만 하면 끝입니다.
  • 권한 변경은 그룹의 정책만 바꾸면 모두에게 일관되게 적용됩니다.
  • 감사 / 점검도 그룹 단위로 깔끔합니다.

규칙: IAM 사용자에는 인라인 정책 / 직접 첨부 정책 금지. 모든 권한은 그룹 또는 역할로.

Role: “임시로 빌려 쓰는” 자격 #

Role은 누구의 자격이 아니라, 무엇이든 임시로 빌려 쓸 수 있는 자격입니다. 영구 비밀번호 / 액세스 키가 없습니다. 대신 누군가 / 무언가가 AssumeRole이라는 호출을 하면, AWS가 임시 자격 (1시간 ~ 12시간 유효)을 발급해 줍니다.

이게 IAM에서 가장 중요한 부분입니다. 처음엔 어렵지만 익숙해지면 IAM의 진짜 힘이 보입니다.

Role이 실제로 쓰이는 경우 #

시나리오누가 AssumeRole 하는가
EC2가 S3에 접근EC2 인스턴스 (자동으로)
Lambda가 DynamoDB에 쓰기Lambda (자동으로)
ECS Task가 다른 서비스 호출Task (자동으로)
다른 AWS 계정 사용자가 이 계정 일부 자원 접근그 사용자가 명시적으로
GitHub Actions가 ECR에 pushOIDC로 GitHub Actions Workflow
임시 권한 상승 (Break-glass)사용자가 명시적으로

EC2 / Lambda / ECS 같은 환경에서는 AWS가 자동으로 AssumeRole을 해서 자격을 인스턴스에 흘려 줍니다. 코드는 그냥 SDK를 부르면 됩니다. 액세스 키를 다룰 필요가 없습니다. 이것이 핵심입니다.

역할의 두 정책 #

역할에는 두 종류의 정책이 붙습니다.

1) Trust Policy (신뢰 정책). 누가 이 역할을 빌릴 수 있는지 정합니다.

EC2가 빌릴 수 있는 역할
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "ec2.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}

Principal 항목에 누가 들어갑니다. 서비스, 다른 계정, 사용자, OIDC provider 등입니다.

2) Permission Policy (권한 정책). 빌린 다음 무엇을 할 수 있는지 정합니다.

역할 안에서 S3 읽기 허용
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::my-bucket/*"
  }]
}

EC2 인스턴스 프로파일 흐름 #

EC2 → S3의 자격 흐름
[EC2 인스턴스]
   │ 1) 인스턴스 메타데이터 (169.254.169.254)에 자격 요청
[IAM]
   │ 2) 인스턴스에 붙은 역할의 임시 자격 발급
[EC2 안의 SDK]
   │ 3) 자격으로 S3 호출
[S3]

EC2 안의 코드는 액세스 키를 모릅니다. boto3 / aws-sdk가 알아서 메타데이터에서 자격을 꺼내 씁니다. 키 노출 사고를 원천적으로 줄여 줍니다.

관리형 정책 vs 인라인 정책 #

정책은 만드는 방식으로 또 나뉩니다.

종류무엇추천
AWS 관리형AWS가 만들어 둔 (예: AdministratorAccess, ReadOnlyAccess)입문 / 표준 역할
고객 관리형내가 만든 정책. 여러 사용자 / 역할에 재사용 가능운영 표준, 권장
인라인한 사용자 / 그룹 / 역할에만 직접 부여한비권장. 재사용 안 됨, 추적 어려움

자주 쓰는 AWS 관리형 정책 #

이름무엇
AdministratorAccess모든 권한. 루트 다음 가장 위험
PowerUserAccessIAM 빼고 거의 모든 권한
ReadOnlyAccess모든 서비스 읽기만
Billing결제 콘솔
<Service>FullAccess (예: AmazonS3FullAccess)한 서비스 전부
<Service>ReadOnlyAccess한 서비스 읽기

처음엔 관리형으로 시작해 점점 좁혀 고객 관리형으로 옮기는 것이 일반적인 흐름입니다.

운영 권한 설계: 통하는 패턴 #

작은 팀에서도 통하는 권한 설계의 뼈대입니다.

1) 그룹 4 + 역할 3 #

단위이름무엇
그룹AdminsAdministratorAccess (MFA 강제)
그룹DevelopersPowerUserAccess + IAM 거부
그룹ReadOnlyReadOnlyAccess
그룹Billing결제 / 비용
역할EC2-AppRole앱이 쓰는 역할 (S3, RDS 등)
역할Lambda-WorkerRole람다용
역할CICDRoleGitHub Actions / CodeBuild가 빌림

2) 권한 경계 (Permission Boundary) #

“이 IAM 사용자는 무엇을 하든 이 한도 안에서만"을 정하는 보호막입니다. 신입 개발자가 새 정책을 만들어 자기 권한을 늘리는 사고를 차단합니다.

패턴
Developers 그룹 → PowerUserAccess
   ↓ 그리고 모든 사용자에 권한 경계 부여
권한 경계 → "DevOnly". dev/* 리소스만 만들 수 있음

3) MFA 강제 #

루트와 모든 IAM 사용자에 적용합니다. 강제 정책의 모양은 #6에서 자세히 다룹니다.

4) 사용자 ↔ 역할 분리 #

사용자 = 사람만. 머신은 모두 역할로 처리합니다. 이게 명확하면 액세스 키 사고가 거의 안 납니다.

5) 조건으로 가드레일 #

개발자가 prod-* 태그 자원 못 만지게
{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {
    "StringEquals": { "aws:ResourceTag/env": "prod" }
  }
}

태그를 일관되게 쓰면 정책 한 줄로 환경 분리가 됩니다.

정책 시뮬레이터: 검증 도구 #

IAM Policy Simulator (policysim.aws.amazon.com)는 사용자 / 그룹 / 역할에 대해 **“이 액션 가능한가?”**를 시뮬레이션해주는 도구입니다. 정책을 변경한 뒤 의도한 대로 됐는지 확인할 때 씁니다.

흐름
1) 사용자 또는 역할 선택
2) 시뮬레이션할 액션 선택 (예: s3:DeleteObject)
3) 리소스 ARN 입력 (선택)
4) "Run Simulation" → Allowed / Denied와 어떤 정책이 영향을 줬는지

#6의 IAM Access Analyzer도 같이 점검에 도움이 됩니다.

IAM 사용자 만들기: 실습 #

여기까지 왔으면 직접 IAM 사용자 한 명을 만들어 두세요. #4 CLI부터는 이 사용자 / 역할이 필요합니다.

실습 순서
1. 콘솔 → IAM → Users → Add users
2. 사용자 이름: 본인 이름 (예: curtis)
3. Console access: 활성화, 비밀번호 자동 생성
4. Attach policies directly: AdministratorAccess (학습용, 나중에 좁히기)
5. 만든 직후 → MFA 즉시 활성화 (#6에서 강제 방법)
6. Access keys: CLI 용 한 개만 발급
7. .csv 다운로드. Secret은 이 화면에서만 보임

이 직후 #3 비용 관리#6 보안 기본으로 넘어갑니다.

자주 만나는 함정 #

1) 사용자에 정책 직접 첨부 #

10명까지는 괜찮아 보이지만, 30명에서 권한이 미묘하게 달라지기 시작합니다. 운영 침입 시 누구의 권한이 어디까지인지 파악할 수 없습니다. 그룹으로 모이도록 합니다.

2) Resource: "*"의 남발 #

처음엔 편하지만 침입 시 피해 범위가 무한대가 됩니다. 가능한 모든 역할에서 ARN으로 좁히세요.

3) 인라인 정책 #

한 번에 적용할 땐 빠르지만 한 달 뒤 누가 추가한 정책인지 알 수 없습니다. 재사용도 안 됩니다. 고객 관리형 정책으로 옮기면 이름이 붙고 버전이 관리됩니다.

4) 액세스 키를 EC2 안에 직접 부여하기 #

EC2 → S3의 자격을 액세스 키로 해결하는 코드가 있습니다. **인스턴스 프로파일 (역할)**로 옮겨야 합니다. 키 회전을 잊으면 사고 위험이 영원히 잠재합니다.

5) “테스트로 만든 사용자"가 그대로 #

전 직원의 액세스 키, 한 번 만들고 잊은 봇 사용자가 남습니다. 30일 / 90일 미사용 사용자는 자동 비활성화 / 삭제 정책을 만듭니다. IAM Credential Report로 한눈에 확인할 수 있습니다.

6) 루트 사용자에 액세스 키 #

#1 함정 #2에서 본 가장 흔한 사고입니다. 루트는 콘솔 + MFA만 쓰고, 액세스 키는 절대 만들지 않습니다.

정리 #

이번 글에서 잡은 것:

  • IAM의 4가지 구성. User (사람 / 머신 영구 자격), Group (사용자 묶음), Role (임시로 빌려 쓰는 자격), Policy (JSON 권한 문서)로 이뤄집니다.
  • 정책의 모양. Effect + Action + Resource (+ Condition)이며, Deny가 Allow를 이깁니다.
  • 사용자에는 정책을 직접 첨부하지 않고 그룹으로 모읍니다.
  • Role의 두 정책. Trust Policy (누가 빌릴 수 있는지)와 Permission Policy (빌린 후 무엇을 할 수 있는지)로 나뉩니다.
  • EC2 / Lambda / ECS는 인스턴스 프로파일 / 실행 역할로 자격을 받으므로, 코드에 키를 넣지 않습니다.
  • 관리형 vs 인라인. 고객 관리형이 운영 표준입니다.
  • 권한 설계 패턴. 그룹 4 + 역할 3, 권한 경계, MFA 강제, 사용자 ↔ 역할 분리, 태그 + Condition 가드레일을 씁니다.
  • 함정. 사용자 직접 정책, Resource:*, 인라인 정책, EC2 안 액세스 키, 잠자는 사용자, 루트 키입니다.

다음: 비용 관리 #

IAM 사용자가 생겼으니 이제 결제 차례입니다. 처음 며칠 동안 가장 큰 사고는 잠자는 자원이 청구서를 키우는 것입니다.

#3 비용 관리: 결제 알림, Cost Explorer, 무료 티어에서는 가입 직후 반드시 켜야 할 결제 알림과 무료 티어 한도 모니터링, 그리고 운영 단계의 Cost Explorer / 태그 전략까지 정리하겠습니다.

X