terraform/modules/iam/main.tf (104 lines of code) (raw):

# https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_iam # https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam#google_project_iam_member ############## Service Accounts ###################################### resource "google_service_account" "sa_tagging_dispatcher" { project = var.project account_id = var.sa_tagging_dispatcher display_name = "Runtime SA for Tagging Dispatcher service" } resource "google_service_account" "sa_tagger" { project = var.project account_id = var.sa_tagger display_name = "Runtime SA for Tagger service" } resource "google_service_account" "sa_tagging_dispatcher_tasks" { project = var.project account_id = var.sa_tagging_dispatcher_tasks display_name = "To authorize PubSub Push requests to Tagging Dispatcher Service" } resource "google_service_account" "sa_tagger_tasks" { project = var.project account_id = var.sa_tagger_tasks display_name = "To authorize PubSub Push requests to Tagger Service" } ############## Service Accounts Access ################################ # Use google_project_iam_member because it's Non-authoritative. # It Updates the IAM policy to grant a role to a new member. # Other members for the role for the project are preserved. #### Dispatcher Tasks Permissions ### resource "google_service_account_iam_member" "sa_tagging_dispatcher_account_user_sa_dispatcher_tasks" { service_account_id = google_service_account.sa_tagging_dispatcher.name role = "roles/iam.serviceAccountUser" member = "serviceAccount:${google_service_account.sa_tagging_dispatcher_tasks.email}" } #### Dispatcher SA Permissions ### # Grant sa_dispatcher access to submit query jobs resource "google_project_iam_member" "sa_tagging_dispatcher_bq_job_user" { project = var.project role = "roles/bigquery.jobUser" member = "serviceAccount:${google_service_account.sa_tagging_dispatcher.email}" } // tagging dispatcher needs to read data from dlp results table and views created inside the solution-managed dataset // e.g. listing tables to be tagged resource "google_bigquery_dataset_access" "sa_tagging_dispatcher_bq_dataset_reader" { dataset_id = var.bq_results_dataset role = "roles/bigquery.dataViewer" user_by_email = google_service_account.sa_tagging_dispatcher.email } #### Tagger Tasks SA Permissions ### resource "google_service_account_iam_member" "sa_tagger_account_user_sa_tagger_tasks" { service_account_id = google_service_account.sa_tagger.name role = "roles/iam.serviceAccountUser" member = "serviceAccount:${google_service_account.sa_tagger_tasks.email}" } #### Tagger SA Permissions ### resource "google_project_iam_custom_role" "tagger-role" { project = var.project role_id = var.tagger_role title = var.tagger_role description = "Used to grant permissions to sa_tagger" permissions = [ "bigquery.tables.setCategory", "datacatalog.taxonomies.get"] } resource "google_project_iam_member" "sa_tagger_role" { project = var.project role = google_project_iam_custom_role.tagger-role.name member = "serviceAccount:${google_service_account.sa_tagger.email}" } // tagger needs to read data from views created inside the solution-managed dataset // e.g. dlp results view resource "google_bigquery_dataset_access" "sa_tagger_bq_dataset_reader" { dataset_id = var.bq_results_dataset role = "roles/bigquery.dataViewer" user_by_email = google_service_account.sa_tagger.email } # to submit query jobs resource "google_project_iam_member" "sa_tagger_bq_job_user" { project = var.project role = "roles/bigquery.jobUser" member = "serviceAccount:${google_service_account.sa_tagger.email}" } ############## DLP Service Account ################################################ # DLP SA must read BigQuery columns tagged by solution-managed taxonomies resource "google_project_iam_member" "dlp_sa_binding" { project = var.project role = "roles/datacatalog.categoryFineGrainedReader" member = "serviceAccount:${var.dlp_service_account}" } # DLP SA must write results to BigQuery table inside of the solution dataset resource "google_bigquery_dataset_iam_member" "dlp_access_bq_dataset" { dataset_id = var.bq_results_dataset role = "roles/bigquery.dataEditor" member = "serviceAccount:${var.dlp_service_account}" } ############## Data Catalog Taxonomies Permissions ################################ locals { # For each parent tag: omit the tag_id and lookup the list of IAM members to grant access to parent_tags_with_members_list = [for parent_tag in var.taxonomy_parent_tags: { policy_tag_name = parent_tag["id"] # lookup the iam_mapping variable with the key <domain>_<classification> # parent_tag.display_name is the classification iam_members = lookup( var.iam_mapping[lookup(parent_tag, "domain", "NA")], lookup(parent_tag, "display_name", "NA"), ["IAM_MEMBERS_LOOKUP_FAILED"] ) }] // flatten the iam_members list inside of parent_tags_with_members_list iam_members_list = flatten([for entry in local.parent_tags_with_members_list:[ for member in lookup(entry, "iam_members", "NA"): { policy_tag_name = lookup(entry, "policy_tag_name", "NA") iam_member = member } ]]) } # Grant permissions for every member in the iam_members_list resource "google_data_catalog_policy_tag_iam_member" "policy_tag_reader" { provider = google-beta count = length(local.iam_members_list) policy_tag = local.iam_members_list[count.index]["policy_tag_name"] role = "roles/datacatalog.categoryFineGrainedReader" member = local.iam_members_list[count.index]["iam_member"] }