79장. IAM Role 활용 — EC2 · ECS Task Role · Execution Role
이 장에서 말하고자 하는 것
앞 장에서 IAM의 4축을 봤다.
이 장은 실전에서 가장 자주 다루는
Role의 활용 패턴
을 정리한다.
특히 ECS 환경에서 헷갈리는 두 Role을 명확히 한다.
- Execution Role
- Task Role
1. Trust Policy vs Permission Policy
Role은 두 종류의 정책을 가진다.
Trust Policy : 누가 이 Role을 받을 수 있나
Permission Policy: 받은 사람이 무엇을 할 수 있나
EC2 인스턴스에 붙이는 Role의 Trust Policy:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "ec2.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}
이러면 “EC2 서비스가 이 Role을 받을 수 있다” 가 된다.
2. EC2 Instance Profile
EC2가 Role을 직접 받을 수는 없다.
중간에 Instance Profile 을 거친다.
[Role]
↓ 담는다
[Instance Profile]
↓ EC2에 붙는다
[EC2 instance]
↓ 임시 자격증명 자동 발급
[Application]
↓ AWS SDK 호출 → S3 / DynamoDB / …
콘솔에서 Role을 만들면 Instance Profile이 자동으로 만들어진다.
Terraform에서는 명시적으로 만들어야 한다.
3. ECS의 두 Role — Execution vs Task
ECS에서는 두 종류의 Role 이 있다.
[ECS Task Definition]
├─ executionRoleArn ← Execution Role
└─ taskRoleArn ← Task Role
Execution Role
Task를 띄우기 위해 ECS 에이전트가 쓰는 권한
- ECR 이미지 pull
- CloudWatch Logs에 로그 쓰기
- Secrets Manager에서 비밀 가져오기 (
secrets필드)
Task Role
Task 안의 컨테이너가 AWS API를 호출할 때 쓰는 권한
- S3 GetObject
- DynamoDB Query
- SQS SendMessage
4. 두 Role을 헷갈리면 일어나는 증상
Task가 시작 안 됨 → Execution Role 문제
- "이미지 못 가져와요"
- "로그 그룹에 못 써요"
- "Secret 못 읽어요"
Task는 떴는데 API 거부됨 → Task Role 문제
- "S3 GetObject denied"
- "DynamoDB Query unauthorized"
이 두 증상이 운영에서 가장 자주 마주친다.
5. Lambda Role
Lambda 함수도 자기 Role을 가진다.
[Lambda]
├─ Execution Role (Lambda가 받음)
│ ├─ CloudWatch Logs 쓰기
│ └─ 함수가 호출할 AWS API 권한
└─ 자동 발급되는 임시 자격증명
ECS와 달리 Execution Role / Task Role 구분이 없다 — Lambda는 한 Role.
6. Cross-Account Role — 다른 계정에 권한 빌려주기
[A 계정의 Role: ReadOnlyRoleForB]
Trust Policy: B 계정만 받을 수 있음
[B 계정 사용자] → AssumeRole → 임시 자격증명 → A 계정 자원 접근
- 멀티 계정 환경에서 표준
- AWS Organizations 환경에 자주 등장
- 외부 서드파티(DataDog · 빌링 도구 등) 에 권한 줄 때도 사용
7. OIDC Federation — 외부 신원으로 Role 받기
GitHub Actions · GitLab · Kubernetes ServiceAccount 같은 외부 신원이
Role을 받을 수 있다.
[GitHub Actions Workflow]
↓ OIDC 토큰 발급
[AWS IAM OIDC Provider]
↓ AssumeRoleWithWebIdentity
[Role: GitHubDeployRole]
↓ 임시 자격증명
[배포 작업]
- CI에 액세스 키를 박지 않는다
- 짧은 임시 자격증명만 사용
- 어느 워크플로우인지 추적 가능
새 CI/CD는 거의 항상 OIDC로 풀어야 한다
8. 우리 서비스에서
Execution Role (공용)
├─ ecr:GetAuthorizationToken
├─ ecr:BatchGetImage
├─ logs:CreateLogStream / PutLogEvents
└─ secretsmanager:GetSecretValue (특정 시크릿만)
Task Role (서비스마다 별도)
orders-task:
├─ rds-db:connect (orders-db 만)
└─ sns:Publish (order-events 토픽만)
users-task:
└─ rds-db:connect (users-db 만)
catalog-task:
└─ dynamodb:Query / GetItem (products 테이블만)
GitHub Actions Role (OIDC)
├─ ecr push
├─ ecs update-service
└─ cloudfront create-invalidation
각 Role은 자기 일에 필요한 권한만 가진다.
9. 직접 확인해보기 — CLI
Role 만들기 (Trust Policy)
aws iam create-role \
--role-name orders-task \
--assume-role-policy-document '{
"Version":"2012-10-17",
"Statement":[{
"Effect":"Allow",
"Principal":{"Service":"ecs-tasks.amazonaws.com"},
"Action":"sts:AssumeRole"
}]
}'
EC2 Instance Profile
aws iam create-instance-profile --instance-profile-name web
aws iam add-role-to-instance-profile \
--instance-profile-name web \
--role-name web-role
AssumeRole로 임시 자격증명 받기 (Cross-Account)
aws sts assume-role \
--role-arn arn:aws:iam::123456789:role/ReadOnly \
--role-session-name my-session
10. 코드로는 이렇게 생겼다 — Terraform (ECS Task Roles)
# Execution Role (모든 ECS Task가 공용으로 받음)
resource "aws_iam_role" "task_execution" {
name = "ecs-task-execution"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "ecs-tasks.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy_attachment" "task_execution_basic" {
role = aws_iam_role.task_execution.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
# orders 서비스 Task Role
resource "aws_iam_role" "orders_task" {
name = "orders-task"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "ecs-tasks.amazonaws.com" }
Action = "sts:AssumeRole"
}]
})
}
resource "aws_iam_role_policy" "orders_task_perms" {
role = aws_iam_role.orders_task.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = "sns:Publish"
Resource = aws_sns_topic.order_events.arn
}
]
})
}
task_role_arn 과 execution_role_arn 을 명확히 분리한다.
11. 이렇게 쓰면 망한다 — 안티패턴
안티패턴 1. Execution Role과 Task Role을 합친다
보안이 약해진다 (불필요한 권한이 컨테이너 안에 그대로 보임).
안티패턴 2. 한 Task Role을 모든 서비스에 공용으로 쓴다
한 서비스의 권한이 모든 서비스에 흘러간다.
서비스마다 별도 Task Role, 각자 최소 권한
안티패턴 3. CI에 IAM User 키를 박는다
키 유출이 곧 운영 사고로 이어진다.
OIDC + AssumeRole로 키 없이 풀어낸다
안티패턴 4. AssumeRole 권한을 너무 넓게 준다
“누구나 어떤 Role이든 받아갈 수 있다” 같은 Trust Policy는 사고난다.
Trust Policy도 최소 범위로
12. 한 줄로 정리
Role은 머신/외부 신원에 임시 자격증명을 발급하는 도구이며,
ECS의 Execution / Task Role 분리와 CI의 OIDC 활용이 운영의 토대다
13. 이 장의 핵심 정리
- Role은 Trust Policy(누가 받을 수 있나) + Permission Policy(무엇을 할 수 있나) 다.
- EC2는 Instance Profile을 거쳐 Role을 받는다.
- ECS는 Execution Role(Task 띄움용) + Task Role(컨테이너 코드용) 두 가지가 있다.
- Lambda는 Execution Role 하나만 가진다.
- Cross-Account · OIDC Federation으로 외부 신원에도 Role을 줄 수 있다.
- CI/CD는 OIDC로 키 없이 운영하는 게 표준이다.