Terraform: Using non-authoritative resources to avoid IAM membership dependency web

One of the most challenging aspects of using Terraform is dealing with external changes and sprawl of dependent objects that may originate outside your control.  Terraform wants to be a system of record and have everything documented in its state as resource/data, however keeping your state in sync when other groups may be doing automation with other tools (or manually) takes continual tending.  You will often hear this referred to as “configuration drift“.

This is especially obvious if using Terraform to manage GCP IAM policy.  If you are attempting to manage roles using the authoritative ‘gcp_project_iam_binding‘, then every entity in that role must be defined.  And every time a user or service account is added to a role, you will have to modify your .tf script and add the entity as a member in the role.

Imagine a popular role in your project like ‘logging.logWriter’.  If you have to rework your independent .tf script that creates GCP loadbalancers every time any entity is added/removed from this common role, that is too much effort.

Luckily, this can be overcome by using a non-authoritative resource, ‘google_project_iam_member‘ which allows you to update IAM policy roles without affecting or caring about others who might hold that same role.

Here is an example of adding ‘myserviceacct1’ to the log writer and metric writer roles.   This non-authoritative role adds it to the existing membership list.

# project
data "google_project" "project" {}

# service account
resource "google_service_account" "my_sa" {
  account_id   = "myserviceacct1"
  display_name = "myserviceacct1"
}

# use non-authoritative resource
# others in the same role are untouched
#
resource "google_project_iam_member" "my_sa_roles" {
  project = var.project

  for_each = toset( ["roles/logging.logWriter","roles/monitoring.metricWriter"] )
  role = each.key

  member = "serviceAccount:${google_service_account.my_sa.email}"
}

If this was done with an authoritative role, all other members in this role would need to be imported as data and referenced.

In a popular, heavily trafficked role of your project, this would require continual tending to keep synced with the terraform state.

 

RESOURCES

terraform.io, IAM policy for projects, resources