IAM Terraform 마이그레이션IAM Terraform 마이그레이션

IAM Terraform 마이그레이션

생성 일시
Sep 8, 2026 06:28 AM
최종 편집 일시
Last updated September 8, 2026
태그
IAM
terraform
AWS
Infra
작성자
@장혜리
Date

콘솔로 만든 IAM을 Terraform 밑으로 옮기기

🎯 목표 설정

지금까지 팀 근두운의 AWS 콘솔에는 IAM 사용자 8명, 그룹 3개(WHS4_Attack, WHS4_Infra, WHS4_SIEM_Detect)가 직접 생성되어 있었다. 반면 identity 모듈에는 이미 이 리소스를 코드로 관리할 수 있는 Terraform 구조가 짜여 있었지만 실제 AWS 상태와는 연결되지 않은 채였다.
이번 작업의 목표는 콘솔로 만든 기존 IAM 리소스를 Terraform state로 편입시켜서, 앞으로의 계정/그룹/권한 변경도 코드 리뷰(PR)를 거치게 만드는 것이다.

기존 코드 구조 파악

identity 폴더는 외부 모듈 없이 리소스를 직접 정의하고 있었고, 사용자·그룹 명단은 members.yaml/groups.yaml이라는 YAML 파일에서 읽어와 for_each로 동적 생성하는 구조였다.
# groups.tf (요약) resource "aws_iam_group" "managed" { for_each = yamldecode(file("${path.module}/groups.yaml")) name = each.key } resource "aws_iam_group_policy_attachment" "managed" { for_each = local.group_policy_pairs group = each.value.group policy_arn = each.value.policy_arn }
 
# users.tf (요약) resource "aws_iam_user" "member" { for_each = yamldecode(file("${path.module}/members.yaml")) name = each.key permissions_boundary = var.permissions_boundary_arn } resource "aws_iam_user_group_membership" "member" { for_each = ... user = each.key groups = each.value.groups }
문제는 members.yaml, groups.yaml 두 파일이 전부 빈 템플릿 상태였다는 것이다. 코드는 준비되어 있었지만, 실제로 무엇을 관리할지는 아무것도 채워지지 않은 채였다.

마이그레이션 과정

1. 실제 AWS 상태 조회

AWS CLI로 그룹 목록, 그룹별 소속 사용자, 그룹별 부착 정책을 전부 조회했다.
aws iam list-groups aws iam get-group --group-name WHS4_Infra aws iam list-attached-group-policies --group-name WHS4_Infra
 

2. YAML 초안 작성

조회 결과를 바탕으로 groups.yaml, members.yaml을 채웠다.
# groups.yaml (일부) WHS4_Infra: policy_arns: - "arn:aws:iam::aws:policy/IAMFullAccess" - "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess" - "arn:aws:iam::aws:policy/AmazonS3FullAccess" - "arn:aws:iam::aws:policy/AWSCloudTrail_FullAccess" - "arn:aws:iam::446413909569:policy/WHS4_SelfAccountManagement"
# members.yaml (일부) hyeri: groups: ["WHS4_Infra", "WHS4_SIEM_Detect"] junhwan: groups: ["WHS4_Infra"]

3. terraform import

resource "aws_iam_group_policy_attachment" "managed" { for_each = { "WHS4_Infra|arn:aws:iam::aws:policy/IAMFullAccess" = { group = "WHS4_Infra" policy_arn = "arn:aws:iam::aws:policy/IAMFullAccess" } } group = each.value.group policy_arn = each.value.policy_arn }
for_each 구문을 이용해 그룹 3개, 사용자 8명, 그룹-정책 attachment 21개, 사용자-그룹 멤버십 8개까지 총 40개 리소스를 import했다.

☁️ 마무리

40개 리소스를 import한 뒤 terraform plan을 돌려 검증했다.
Plan: 16 to add, 8 to change, 0 to destroy
 
  • 추가 16개
    • 사용자 8명 × (self_service_credentials, require_mfa) 정책 attachment
    • 코드에는 정의되어 있었지만 AWS에는 아직 적용되지 않았던 항목이다.
  • 변경 8개
    • 사용자별 태그(Project, ManagedBy, Module, Name) 반영
    • 파괴적 변경은 없다.
  • 삭제 0개
    • 삭제되는 리소스는 없었다.
 
plan 결과가 예상한 항목으로만 구성된 것을 확인한 뒤 PR을 올렸다. taehyung의 개별 정책과, MFA 강제 정책을 실제로 apply할 시점은 팀 확인을 거쳐 별도로 진행할 예정이다.
이번 작업으로 콘솔에서 만들어졌던 IAM 리소스가 전부 Terraform state 아래로 들어왔다. 다음 단계는 이 구조를 기준으로 팀원별 필요한 권한을 다시 조율하고, 최종 IAM 구조를 코드로 정리하는 것이다.
flowchart TB
    A["AWS 콘솔로 생성된<br/>기존 IAM 사용자 8명 · 그룹 3개"]
    B["AWS CLI 조회<br/>list-groups / get-group / list-attached-group-policies"]
    C["groups.yaml / members.yaml<br/>초안 작성"]
    D["terraform import<br/>(그룹 3 + 사용자 8 + attachment 21 + 멤버십 8 = 40개)"]
    E["terraform plan<br/>16 추가 / 8 변경 / 0 삭제"]
    F["PR 생성 · 팀 리뷰"]

    A --> B --> C --> D --> E --> F