본문으로 건너뛰기

GCP 서비스 계정 역할 관리 (Terraform)

개요

이 문서는 Terraform을 사용하여 Google Cloud Platform (GCP) 서비스 계정에 할당된 역할을 관리하는 방법을 설명합니다. 특히 기존 서비스 계정에 새로운 역할(커스텀 역할 포함)을 추가하는 방법에 중점을 둡니다.

DTA-WIDE 시스템에서는 다양한 환경(개발, 스테이징, 프로덕션)에서 Terraform 서비스 계정이 인프라를 관리하는 데 필요한 권한을 자동화된 방식으로 부여하기 위해 이 모듈을 사용합니다.

구성 및 아키텍처

  • 관리 대상: 서비스 계정(terraform@dta-cloud-de-[dev|stage|prod].iam.gserviceaccount.com)
  • 관리 수준: 프로젝트 레벨 역할 할당
  • 관리 도구: Terraform, Terragrunt
  • 형상 관리: Git (이 저장소)

디렉토리 구조

서비스 계정별로 구분된 구조를 사용하여 관리의 명확성을 높였습니다:

infrastructure/
├── terraform/
│ └── modules/
│ └── iam_service_account_roles/ # 공통 모듈 (재사용 가능)
└── terragrunt/
├── root.hcl # 모든 환경에 공통 설정
├── dev/
│ └── iam/
│ └── terraform_service_account/ # terraform@dta-cloude-de-dev 서비스 계정 전용
├── stage/
│ └── iam/
│ └── terraform_service_account/
└── prod/
└── iam/
└── terraform_service_account/

Terragrunt 구성

루트 설정 (root.hcl)

모든 Terragrunt 설정에 공통으로 적용되는 설정을 root.hcl 파일에 정의합니다:

# Google Cloud 공통 변수 정의
locals {
# 프로젝트 ID 접두사
project_prefix = "dta-cloud-de"

# 현재 경로에서 환경 이름 추출 (dev, stage, prod)
path_parts = split("/", path_relative_to_include())
env = path_parts[0]

# 환경별 프로젝트 ID 생성
project_id = "${local.project_prefix}-${local.env}"
}

# 모든 Terragrunt 모듈에서 사용할 원격 상태 설정
remote_state {
backend = "gcs"

config = {
project = local.project_id
location = "europe-west3"
bucket = "${local.project_id}-terraform-state"
prefix = "${path_relative_to_include()}/terraform.tfstate"
}
}

서비스 계정별 설정

각 서비스 계정에 대한 Terragrunt 설정 파일은 다음과 같이 구성됩니다:

include {
path = find_in_parent_folders("root.hcl")
}

terraform {
source = "../../../../terraform/modules/iam_service_account_roles"
}

inputs = {
project_id = "dta-cloud-de-dev"
service_account_email = "terraform@dta-cloud-de-dev.iam.gserviceaccount.com"

roles = [
# 기존 역할들
"roles/cloudbuild.builds.builder",
# ... 기타 역할들 ...

# 새 커스텀 역할
"projects/dta-cloud-de-dev/roles/TerraformRole"
]
}

Terraform을 통한 서비스 계정 역할 관리

구현 요소

서비스 계정의 역할을 Terraform으로 관리하기 위해 다음 요소를 사용합니다:

  1. Terraform 모듈: 서비스 계정에 역할을 부여하는 google_project_iam_member 리소스를 정의 (/infrastructure/terraform/modules/iam_service_account_roles/)
  2. Terragrunt 구성: 환경별, 서비스 계정별 설정값 관리 (/infrastructure/terragrunt/[dev|stage|prod]/iam/[service_account_name]/)

Terraform 모듈 구조 (/infrastructure/terraform/modules/iam_service_account_roles/)

모듈은 다음 파일들로 구성됩니다:

  • main.tf: 서비스 계정에 역할을 할당하는 리소스 정의
  • variables.tf: 입력 변수 정의 (프로젝트 ID, 서비스 계정 이메일, 역할 목록)
  • outputs.tf: 출력값 정의 (할당된 역할 목록, 서비스 계정 이메일)

주요 리소스는 다음과 같습니다:

resource "google_project_iam_member" "service_account_roles" {
count = length(var.roles)

project = var.project_id
role = var.roles[count.index]
member = "serviceAccount:${var.service_account_email}"
}

이 리소스는 서비스 계정에 지정된 역할 목록을 각각 할당합니다. count를 사용하여 여러 역할을 순회하며 할당합니다.

새로운 서비스 계정 추가 방법

새로운 서비스 계정에 대한 역할 관리가 필요한 경우, 다음 단계를 따릅니다:

  1. 디렉토리 생성: 각 환경에 해당 서비스 계정 이름을 딴 디렉토리를 생성합니다.

    mkdir -p infrastructure/terragrunt/dev/iam/new_service_account_name
    mkdir -p infrastructure/terragrunt/stage/iam/new_service_account_name
    mkdir -p infrastructure/terragrunt/prod/iam/new_service_account_name
  2. Terragrunt 설정 생성: 각 디렉토리에 terragrunt.hcl 파일을 생성하고 해당 서비스 계정의 정보와 역할을 설정합니다.

    include {
    path = find_in_parent_folders("root.hcl")
    }

    terraform {
    source = "../../../../terraform/modules/iam_service_account_roles"
    }

    inputs = {
    project_id = "dta-cloud-de-dev"
    service_account_email = "new-account@dta-cloud-de-dev.iam.gserviceaccount.com"
    roles = [ ... ]
    }
  3. 기존 역할 확인: 서비스 계정의 현재 역할을 확인하고 Terragrunt 설정에 포함합니다.

    gcloud projects get-iam-policy PROJECT_ID --format=json | jq '.bindings[] | select(.members[] | contains("SERVICE_ACCOUNT_EMAIL"))'

배포 방법

사전 요구 사항

  1. 대상 환경의 GCP 프로젝트(dta-cloud-de-[dev|stage|prod])가 존재해야 합니다.
  2. 서비스 계정이 이미 생성되어 있어야 합니다.
  3. Terraform 및 Terragrunt가 로컬 또는 CI/CD 환경에 설치되어 있어야 합니다.
  4. 배포를 실행하는 주체(사용자 또는 서비스 계정)는 대상 프로젝트에 대한 roles/resourcemanager.projectIamAdmin 권한을 가지고 있어야 합니다.

기존 역할 확인

서비스 계정의 현재 역할을 확인하기 위해 다음 명령어를 실행합니다:

gcloud projects get-iam-policy dta-cloud-de-dev --format=json | jq '.bindings[] | select(.members[] | contains("terraform@dta-cloud-de-dev.iam.gserviceaccount.com"))'

위 명령어 결과를 참고하여 Terragrunt 설정 파일의 roles 목록을 업데이트합니다.

배포 단계

각 환경별, 서비스 계정별 디렉토리로 이동하여 다음 명령어를 실행합니다:

  • 역할 설정 배포:
    cd infrastructure/terragrunt/dev/iam/terraform_service_account
    terragrunt init
    terragrunt plan # 변경 사항 확인
    terragrunt apply # 확인 후 적용

모범 사례

  • 서비스 계정별 분리: 각 서비스 계정의 역할은 별도의 디렉토리에서 관리하여 명확성을 높입니다.
  • 기존 역할 유지: 서비스 계정이 이미 가진 역할을 Terragrunt 설정에 포함하여 실수로 제거되지 않도록 합니다.
  • 최소 권한 원칙: 서비스 계정에는 필요한 최소한의 권한만 부여합니다.
  • 환경별 분리: 개발, 스테이징, 프로덕션 환경마다 적절한 권한 세트를 별도로 관리합니다.
  • 정기적 검토: 서비스 계정의 역할 목록을 주기적으로 검토하여 불필요한 권한을 제거합니다.

문제 해결

  • 권한 충돌: 동일한 역할이 다른 방식(예: GCP 콘솔)으로 추가된 경우, Terraform 적용 시 오류가 발생할 수 있습니다. 이 경우 terragrunt import 명령을 사용하여 상태를 동기화해야 할 수 있습니다.
  • 역할 미적용: 서비스 계정에 적용한 역할이 즉시 반영되지 않는 경우, GCP의 캐시 시간(최대 몇 분) 때문일 수 있습니다. 잠시 기다렸다가 다시 확인합니다.
  • Terragrunt 중첩 포함 오류: Terragrunt 구성에서 find_in_parent_folders()를 여러 레벨에서 사용하면 중첩 포함 오류가 발생할 수 있습니다. 이 경우 find_in_parent_folders("root.hcl")과 같이 구체적인 파일명을 지정해야 합니다.

변경 이력

버전날짜작성자변경 내용
0.1.02025-03-29(Gemini)서비스 계정 역할 관리 문서 초기 생성
0.2.02025-03-29(Gemini)서비스 계정별 디렉토리 구조로 변경
0.3.02025-03-29(Gemini)Terragrunt 구성 개선 (root.hcl 사용)