본문 바로가기

개발하자

Terraform GCP 서비스 계정에 IAM 역할 할당

반응형

Terraform GCP 서비스 계정에 IAM 역할 할당

나는 다음을 사용하고 있다

resource "google_service_account" "store_user" {
  account_id   = "store-user"
  display_name = "Storage User"
}

resource "google_project_iam_binding" "store_user" {
  project = var.project_id
  role    = "roles/storage.admin"
  members = [
    "serviceAccount:${google_service_account.store_user.email}"
  ]
}

SA를 생성하고 스토리지 관리자 역할을 할당한다는 점에서 잘 작동합니다. 좋아요. 하지만 이 SA에게 4가지 역할을 줘야 해요. 다음과 같은 반복 바인딩/역할 블록이 있는 데이터 블록을 사용하는 것을 포함하여 모든 방법을 시도했습니다:

data "google_iam_policy" "store_user_roles" {
  binding {
    role = "roles/storage.admin"
    members = [
      "serviceAccount:${google_service_account.store_user.email}",
    ]
  }
  binding {
    role = "roles/pubsub.admin"
    members = [
      "serviceAccount:${google_service_account.store_user.email}",
    ]
  }
}

이상하게도 실행되지만 SA는 역할/권한을 얻지 못합니다. 나는 여기저기서 발견한 다양한 다른 예들을 시도했지만 성공하지 못했다. 이 일을 어떻게 할 수 있는지 누가 나에게 올바른 방향으로 밀어줄 수 있을까요?

// 업데이트. 다음 사항이 효과가 있었습니다:

resource "google_project_iam_binding" "storage-iam" {
    project = var.project_id
    role = "roles/storage.admin"
    members = [
        "serviceAccount:${google_service_account.store_user.email}",
    ]
}
resource "google_project_iam_binding" "pubsub-iam" {
    project = var.project_id
    role = "roles/pubsub.admin"
    members = [
        "serviceAccount:${google_service_account.store_user.email}",
    ]
}



나는 이것이 이 자원으로 달성된다고 생각한다:

https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam

따라서 데이터 소스를 제외한 코드는 취향에 따라 변경됩니다:

resource "google_service_account_iam_binding" "storage-iam" {
  service_account_id = google_service_account.store_user.name
  role               = "roles/storage.admin"

  members = [
    "serviceAccount:${google_service_account.store_user.email}",
  ]
}

resource "google_service_account_iam_binding" "pubsub-iam" {
  service_account_id = google_service_account.store_user.name
  role               = "roles/pubsub.admin"

  members = [
    "serviceAccount:${google_service_account.store_user.email}",
  ]
}



또 다른 대안은 루프를 사용하는 것입니다. 다음은 루프를 사용하는 샘플 코드입니다.

변수.tf

variable "rolesList" {
type =list(string)
default = ["roles/storage.admin","roles/pubsub.admin"]
}

service-account.tf

resource "google_service_account" "store_user" {
account_id   = "store-user"
display_name = "Storage User"
}

resource "google_project_iam_binding" "store_user" {
project = var.project_id
count = length(var.rolesList)
role =  var.rolesList[count.index]
members = [
  "serviceAccount:${google_service_account.store_user.email}"
]
}

루프를 사용할 때 Terraform은 상태 파일의 값을 가진 인덱스 맵을 유지합니다. 쉽게 말해, 단순히 역할을 원하지 않는다는 이유로 목록에서 첫 번째 요소를 제거하면 Terraform은 인덱스 2(이전 목록의)에서 모든 요소를 제거한 다음 다시 적용합니다.

또한, 같은 역할에 바인딩된 Terraform 외부에 생성된 사용자 또는 SA가 있으면 GCP가 향후 실행에서 제거하기 때문에 대신 사용하는 것을 선호합니다(TF 적용).




이를 수행하는 다른 두 가지 방법이 있습니다:

  1. for_each 변수를 사용하고 내부에 문자열을 설정합니다

    resource "google_project_iam_binding" "store_user" {
       project  = var.project_id
       for_each = toset([
         "roles/storage.admin",
         "roles/pubsub.admin",
       ])
       role     = each.value
       members  = [
          "serviceAccount:${google_service_account.store_user.email}"
       ]
     }
    
  2. sa_roles 변수를 정의하고 for_each in에 사용합니다

    variable "sa_roles" {
      type = set(string)
      default = [
       "roles/storage.admin",
       "roles/pubsub.admin",
      ]
    }
    
    resource "google_project_iam_binding" "store_user" {
      project  = var.project_id
      for_each = var.sa_roles
      role     = each.value
      members  = [
       "serviceAccount:${google_service_account.store_user.email}"
      ]
    }
    

반응형