주니어 개발자가 급한 마음에 액세스 키를 코드에 박고 깃허브 공개 저장소에 푸시했습니다. 3시간 뒤, 봇이 키를 긁어가 전 세계 리전에 고성능 인스턴스 수십 대를 띄워 암호화폐를 채굴했습니다. 다음 날 청구서는 수천만 원. 클라우드 사고의 압도적 1위는 해킹이 아니라 '권한을 잘못 다룬 것'입니다. IAM은 멋진 기능이 아니라 안전벨트입니다.
- 1루트 계정을 왜·어떻게 보호하는지 설명할 수 있다
- 2IAM 사용자·그룹·역할·정책의 관계를 구분할 수 있다
- 3역할(Role)과 임시 자격증명이 영구 키보다 안전한 이유를 안다
- 4최소 권한 원칙을 '좁게 주고 넓히는' 방식으로 실천할 수 있다
- 5액세스 키 하드코딩 같은 대표 사고 패턴을 피할 수 있다
루트 계정 — 금고에 넣고 거의 열지 않는다
루트는 권한을 '제한할 수 없다'
계정을 만들면 처음 주어지는 루트(root) 는 결제 수단 변경, 계정 폐쇄까지 무엇이든 할 수 있고, 그 권한을 줄일 수 없습니다. 그래서 루트가 탈취되면 피해가 무한대입니다.
철칙: ① 루트에 MFA(다단계 인증) 를 걸고, ② 루트 액세스 키는 만들지 않거나 삭제하고, ③ 일상 작업은 권한이 제한된 IAM 사용자/역할로 한다. 루트는 결제 정보 변경처럼 정말 루트만 할 수 있는 일에만, 1년에 몇 번 꺼냅니다.
IAM의 네 조각 — 사용자·그룹·역할·정책
누가(주체) × 무엇을 할 수 있나(정책)
IAM은 "누가 무엇을 할 수 있는가"를 정의합니다.
- 사용자(User): 사람이나 앱의 고정된 정체. 영구 자격증명(비밀번호/액세스 키)을 가짐.
- 그룹(Group): 사용자 묶음. '개발팀' 그룹에 정책을 붙이면 소속 사용자 전체에 적용 — 사람마다 권한을 따로 주지 않아 관리가 쉬움.
- 역할(Role): 영구 키 없이 잠깐 빌려 쓰는 권한 묶음. 사람·인스턴스·다른 계정이 '맡아서(assume)' 임시 자격증명을 발급받음.
- 정책(Policy): "어떤 자원에 어떤 액션을 Allow/Deny" 규칙을 적은 JSON. 위 주체들에 붙여 권한을 부여.

왜 역할이 키보다 안전한가
EC2 인스턴스가 S3에 파일을 올려야 한다고 합시다. 나쁜 방법은 액세스 키를 코드/환경변수에 박는 것입니다 — 저장소가 털리면 키가 털립니다. 좋은 방법은 인스턴스에 IAM 역할을 붙이는 것입니다. 그러면 SDK가 자동으로 역할의 임시 자격증명(수 시간마다 자동 회전)을 받아 씁니다. 코드는 키를 전혀 모릅니다. 유출·회전·폐기 문제가 통째로 사라집니다.
액세스 키 발급 — 정말 필요한가?
안전한 실행 조건: EC2/Lambda 등 클라우드 내부 주체는 역할(Role)로 대체 가능하면 키를 만들지 않는다. 외부 CI 등 불가피한 경우만, 최소 권한 정책을 붙이고 정기적으로 회전·폐기한다.
실행 전 반드시 확인
- 이 작업을 역할(Role)로 대체할 수 없는지 먼저 검토했는가
- 발급할 키에 최소 권한 정책만 붙였는가(AdministratorAccess 금지)
- 키를 안전한 비밀 저장소(Secrets Manager 등)에 보관하고 깃에 올리지 않는가
- 사용하지 않는 오래된 키를 주기적으로 비활성화·삭제하는가
aws iam create-access-key --user-name some-user위 항목을 모두 확인한 후 복사할 수 있습니다
현재 사용자에게 어떤 관리형 정책이 붙어 있는지 확인합니다. 과한 권한(특히 Administrator)이 붙어 있지 않은지 점검합니다.
ME=$(aws iam get-user --query "User.UserName" --output text)
aws iam list-attached-user-policies --user-name "$ME" --output table
------------------------------------------------------
| ListAttachedUserPolicies |
+----------------------+-----------------------------+
| PolicyName | PolicyArn |
+----------------------+-----------------------------+
| ReadOnlyAccess | arn:aws:iam::aws:policy/... |
+----------------------+-----------------------------+
aws iam list-attached-user-policies계정 차원의 보안 상태를 요약으로 확인합니다. MFA 미설정·과다 키 같은 위험 신호를 봅니다.
aws iam get-account-summary \
--query "SummaryMap.{Users:Users,MFADevices:MFADevices,AccessKeysPerUserQuota:AccessKeysPerUserQuota}"
{
"Users": 5,
"MFADevices": 5,
"AccessKeysPerUserQuota": 2
}
aws iam get-account-summary- list-attached-user-policies에 AdministratorAccess가 보이면 — 일상 사용자에 전권은 위험 신호. 역할 분리·정책 축소 검토
- Users 수 대비 MFADevices 수 — 사용자보다 MFA 기기가 적으면 MFA 미설정 계정 존재. 전원 MFA가 기본
- 오래되고 마지막 사용 기록이 없는 액세스 키 — 잊혀진 키는 공격 표면. 비활성화 후 삭제
- 역할로 대체 가능한데 키를 쓰는 앱/인스턴스 — 영구 키를 역할 기반 임시 자격증명으로 전환 대상
상황: 역할로 받은 임시 자격증명으로 호출하다가 토큰 만료·무효 오류.
원인: 역할의 임시 자격증명은 수명이 있습니다(기본 1시간 등). 오래된 세션을 계속 쓰거나, 캐시된 만료 토큰을 재사용하면 발생. 영구 키와 달리 '잠깐 빌린' 것이라 갱신이 필요합니다.
진단: aws sts get-caller-identity로 현재 자격증명이 살아 있는지 확인. assumed-role 세션이면 만료 시각 점검.
해결: SDK/CLI는 보통 자동 갱신하므로, 직접 토큰을 캐싱했다면 그 로직을 제거하고 SDK가 갱신하도록 맡김. 인스턴스·Lambda는 역할을 붙이면 자동 회전되니 수동 토큰 관리를 하지 않는 게 정답.
실무에서 IAM은 '한 번 설정하고 끝'이 아니라 지속적으로 줄여나가는 대상입니다. 처음엔 일이 막히지 않게 넓게 줬다가, Access Analyzer·CloudTrail로 "실제로 쓰는 권한"을 확인해 안 쓰는 권한을 깎아냅니다. 보안 감사에서 가장 먼저 보는 것도 "전권을 가진 사용자가 몇 명인가"입니다.
조직이 커지면 계정을 여러 개로 나누고(운영/개발/결제 분리) 중앙에서 가드레일을 거는 멀티계정 거버넌스로 확장됩니다 — [[cloud-observability-governance]]에서 다룹니다. 권한 관리는 [[cloud-why]]에서 본 '책임 공유 모델'에서 고객 책임의 핵심입니다.
다음 모듈에서는 본격적으로 컴퓨트로 들어가, 가상 서버(EC2)를 띄울 때 만나는 인스턴스 타입·AMI·키페어·보안그룹을 다룹니다.