简体   繁体   中英

Terraform GCP Assign IAM roles to service account

I'm using the following

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}"
  ]
}

Which works well, in that it creates the SA and assigns it the storage admin role. Great. But I need to give this SA about 4 roles. I have tried all manner of things, including using a data block with repeating bindings/roles blocks like this:

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}",
    ]
  }
}

Oddly, that runs, but the SA does not get the roles/permissions. I've tried various other examples I've found here and there but with no success. Can someone please give me a shove in the right direction for how to accomplish this?

// Update. The following did work for me:

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}",
    ]
}

Another alternate would be to use a loop. Here is some sample code using a count loop.

variables.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}"
]
}

Please note that when using a count loop, Terraform maintains a map of index with the values in the state file. In simpler terms, if you remove the 1st element from the list simply because we don't want the role then Terraform will remove all the elements from index 2 (of the older list) and then apply them back.

Also, I prefer using google_project_iam_member instead of google_project_iam_binding because when using google_project_iam_binding if there are any users or SAs created outside of Terraform bound to the same role, GCP would remove them on future runs (TF Apply).

I think this is achieved with this resource:

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

So with your code, minus the data sources, alter to taste:

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}",
  ]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM