4-projects/modules/data_domain/iam.tf (384 lines of code) (raw):
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
locals {
project_iam_roles = merge(flatten([
for sa, config in local.project_iam : [
for role in config.roles : {
"${sa}.${role}" = {
member = config.member
role = role
project = config.project
}
}
]
])...)
project_iam = {
# data ingestion iam
"ngst-compute" = {
member = "serviceAccount:${local.data_governance_project_number}-compute@developer.gserviceaccount.com",
roles = [
"roles/bigquery.user",
"roles/bigquery.dataViewer"
],
project = module.ingestion_project.project_id
}
"ngst-dlp-api" = {
member = "serviceAccount:service-${local.data_governance_project_number}@dlp-api.iam.gserviceaccount.com",
roles = [
"roles/bigquery.admin"
],
project = module.ingestion_project.project_id
}
"ngst-dataflow-controller-reid" = {
member = "serviceAccount:${google_service_account.ingestion_service_accounts["sa-dataflow-controller"].email}",
roles = distinct(concat(local.additional_project_roles, local.default_data_ingestion_project_roles)),
project = module.ingestion_project.project_id
}
"ngst-pubsub-writer" = {
member = "serviceAccount:${google_service_account.ingestion_service_accounts["sa-pubsub-writer"].email}",
roles = distinct(concat(local.additional_project_roles, local.default_data_ingestion_project_roles)),
project = module.ingestion_project.project_id
}
# non confidential iam
"ncnf-report-engine" = {
member = "serviceAccount:${local.data_governance_sa_report_engine}",
roles = [
"roles/bigquery.jobUser",
"roles/bigquery.dataViewer",
]
project = module.nonconfidential_project.project_id
}
"ncnf-record-manager" = {
member = "serviceAccount:${local.data_governance_sa_record_manager}",
roles = [
"roles/datacatalog.searchAdmin",
"roles/datacatalog.entryViewer",
"roles/bigquery.dataEditor",
]
project = module.nonconfidential_project.project_id
}
"ncnf-dataflow-controller-reid" = {
member = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
roles = toset(local.nonconfidential_data_project_roles),
project = module.nonconfidential_project.project_id
}
"ncnf-dataflow-controller" = {
member = "serviceAccount:${google_service_account.ingestion_service_accounts["sa-dataflow-controller"].email}",
roles = toset(local.nonconfidential_data_project_roles),
project = module.nonconfidential_project.project_id
}
"ncnf-tf-injest-sa" = {
member = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-ingest"]}",
roles = [
"roles/resourcemanager.projectIamAdmin",
"roles/bigquery.admin",
]
project = module.nonconfidential_project.project_id
}
"ncnf-cloud-run" = {
member = "serviceAccount:${local.data_governance_sa_cloud_run}",
roles = toset(local.nonconfidential_data_project_roles),
project = module.nonconfidential_project.project_id
}
"ncnf-cloud-function" = {
member = "serviceAccount:${local.data_governance_sa_cloud_function}",
roles = toset(local.cloud_function_project_roles),
project = module.nonconfidential_project.project_id
}
"ncnf-tag-creator" = {
member = "serviceAccount:${local.data_governance_sa_tag_creator}",
roles = toset(local.nonconfidential_tag_creator_project_roles),
project = module.nonconfidential_project.project_id
}
"ncnf-dlp-api" = {
member = "serviceAccount:service-${local.data_governance_project_number}@dlp-api.iam.gserviceaccount.com",
roles = ["roles/bigquery.admin"],
project = module.nonconfidential_project.project_id
}
"ncnf-data-viewer" = {
member = "group:${var.non_confidential_consumers_viewers_group_email}",
roles = [
"roles/bigquery.dataViewer",
"roles/bigquery.jobUser",
],
project = module.nonconfidential_project.project_id
}
"ncnf-fine-grained-data-viewer" = {
member = "group:${var.non_confidential_fine_grained_data_viewer}",
roles = ["roles/datacatalog.categoryFineGrainedReader"],
project = module.nonconfidential_project.project_id
}
"ncnf-encrypted-data-viewer" = {
member = "group:${var.non_confidential_encrypted_data_viewer}",
roles = ["roles/cloudkms.cryptoKeyDecrypterViaDelegation"],
project = module.nonconfidential_project.project_id
}
"ncnf-masked-data-viewer" = {
member = "group:${var.non_confidential_masked_data_viewer}",
roles = ["roles/bigquerydatapolicy.maskedReader"],
project = module.nonconfidential_project.project_id
}
#confidential iam
"cnf-dataflow-controller-reid" = {
member = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
roles = toset(local.confidential_project_roles),
project = module.confidential_project.project_id
}
"cnf-cloud-function" = {
member = "serviceAccount:${local.data_governance_sa_cloud_function}",
roles = toset(local.cloud_function_project_roles),
project = module.confidential_project.project_id
}
"cnf-data-viewer" = {
member = "group:${var.confidential_consumers_viewers_group_email}",
roles = [
"roles/bigquery.dataViewer",
"roles/bigquery.jobUser",
],
project = module.confidential_project.project_id
}
#artifacts iam
"artifact-storage-admin" = {
member = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-ingest"]}",
roles = ["roles/storage.admin"],
project = local.app_infra_artifacts_project_id
}
"artifact-cnf-storage-admin" = {
member = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-conf"]}",
roles = ["roles/storage.admin"],
project = local.app_infra_artifacts_project_id
}
"artifact-dataflow-sa" = {
member = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
roles = toset(local.artifacts_project_roles),
project = local.app_infra_artifacts_project_id
}
"artifacts-cnf-dataflow-sa" = {
member = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
roles = toset(local.artifacts_project_roles),
project = local.app_infra_artifacts_project_id
}
#governance iam
"governance-dataflow-sa" = {
member = "serviceAccount:${google_service_account.ingestion_service_accounts["sa-dataflow-controller"].email}",
roles = toset(local.governance_project_roles),
project = local.data_governance_project_id
}
"governance-dataflow-reid-sa" = {
member = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
roles = toset(local.governance_project_roles),
project = local.data_governance_project_id
}
"governance-ncf-prj-sa" = {
member = "serviceAccount:${module.nonconfidential_project.sa}",
roles = [
"roles/datacatalog.viewer",
]
project = local.data_governance_project_id
}
# service catalog
"ngst-service-catalog" = {
member = "serviceAccount:${module.ingestion_project.sa}",
roles = [
"roles/logging.logWriter",
"roles/storage.admin",
"roles/bigquery.admin",
"roles/cloudkms.admin",
"roles/dataflow.admin",
"roles/pubsub.admin",
"roles/secretmanager.secretAccessor",
"roles/serviceusage.serviceUsageConsumer",
]
project = module.ingestion_project.project_id
}
"ncnf-service-catalog" = {
member = "serviceAccount:${module.nonconfidential_project.sa}",
roles = [
"roles/logging.logWriter",
"roles/storage.admin",
"roles/bigquery.admin",
]
project = module.nonconfidential_project.project_id
}
"ngst-cloud-build" = {
member = "serviceAccount:${module.ingestion_project.project_number}@cloudbuild.gserviceaccount.com",
roles = [
"roles/logging.logWriter",
"roles/storage.admin",
]
project = module.ingestion_project.project_id
}
"ncnf-cloud-build" = {
member = "serviceAccount:${module.nonconfidential_project.project_number}@cloudbuild.gserviceaccount.com",
roles = [
"roles/logging.logWriter",
"roles/storage.admin",
]
project = module.nonconfidential_project.project_id
}
}
default_data_ingestion_project_roles = [
"roles/pubsub.subscriber",
"roles/pubsub.editor",
"roles/storage.objectViewer",
"roles/dataflow.worker",
"roles/compute.admin",
"roles/storage.admin",
"roles/monitoring.metricWriter",
"roles/serviceusage.serviceUsageConsumer"
]
bigquery_read_roles = [
"roles/bigquery.jobUser",
"roles/bigquery.dataEditor",
"roles/serviceusage.serviceUsageConsumer"
]
additional_project_roles = var.enable_bigquery_read_roles ? local.bigquery_read_roles : []
# data_ingestion_project_roles = distinct(concat(local.additional_project_roles, local.default_data_ingestion_project_roles))
governance_project_roles = [
"roles/dlp.user",
"roles/dlp.inspectTemplatesReader",
"roles/dlp.deidentifyTemplatesReader",
]
# governance_project_roles_confidential = [
# "roles/dlp.user",
# "roles/dlp.inspectTemplatesReader",
# "roles/dlp.deidentifyTemplatesReader"
# ]
nonconfidential_data_project_roles = [
"roles/bigquery.dataEditor",
"roles/bigquery.jobUser"
]
nonconfidential_tag_creator_project_roles = [
"roles/bigquery.dataOwner",
"roles/cloudkms.viewer",
"roles/datalineage.viewer",
"roles/bigquery.metadataViewer",
"roles/bigquery.dataEditor",
"roles/bigquery.resourceViewer",
]
cloud_function_project_roles = [
"roles/bigquery.dataViewer",
"roles/bigquery.jobUser",
"roles/orgpolicy.policyViewer",
"roles/datalineage.viewer",
]
# nonconfidential_project_roles_confidential = [
# "roles/bigquery.dataViewer",
# "roles/bigquery.jobUser",
# ]
confidential_project_roles = [
"roles/compute.admin",
"roles/bigquery.dataEditor",
"roles/bigquery.jobUser",
"roles/dataflow.worker",
"roles/storage.admin",
"roles/storage.objectAdmin",
"roles/serviceusage.serviceUsageConsumer",
]
artifacts_project_roles = [
"roles/artifactregistry.repoAdmin",
"roles/artifactregistry.reader"
]
secret_manager_access_sas = {
"ingestion" = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-ingest"]}",
"confidential" = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-conf"]}",
"reidentification" = "serviceAccount:${google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].email}",
"identification" = "serviceAccount:${google_service_account.ingestion_service_accounts["sa-dataflow-controller"].email}",
}
all_projects = {
"ingestion" = module.ingestion_project,
"confidential" = module.confidential_project,
"nonconfidential" = module.nonconfidential_project,
}
data_governance_state_bucket_access = {
"ingestion" = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-ingest"]}",
"nonconfidential" = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-non-conf"]}",
"confidential" = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-conf"]}",
}
}
########################################
# # Data ingestion project
########################################
resource "google_project_iam_member" "data_ingestion_project_iam" {
for_each = local.project_iam_roles
project = each.value.project
role = each.value.role
member = each.value.member
}
resource "google_service_account_iam_member" "project_sa_user_ingest" {
service_account_id = google_service_account.ingestion_service_accounts["sa-dataflow-controller"].name
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${module.ingestion_project.sa}"
}
resource "google_service_account_iam_member" "terraform_sa_user_ingest" {
service_account_id = google_service_account.ingestion_service_accounts["sa-dataflow-controller"].name
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-ingest"]}"
}
resource "google_service_account_iam_member" "terraform_sa_service_account_user_confidential" {
service_account_id = google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].name
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${module.confidential_project.sa}"
}
resource "google_service_account_iam_member" "project_sa_user_confidential" {
service_account_id = google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].name
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${module.confidential_project.sa}"
}
resource "google_service_account_iam_member" "terraform_sa_user_confidential" {
service_account_id = google_service_account.confidential_service_accounts["sa-dataflow-controller-reid"].name
role = "roles/iam.serviceAccountUser"
member = "serviceAccount:${local.app_infra_pipeline_service_accounts["${var.data_domain.name}-conf"]}"
}
########################################
# IAM for Governance Project
########################################
// State bucket access
resource "google_storage_bucket_iam_member" "data_governance_state_bucket" {
for_each = local.data_governance_state_bucket_access
bucket = local.data_governance_tf_state_bucket
role = "roles/storage.objectViewer"
member = each.value
}
########################################
# IAM for Common Secret Access
########################################
data "google_secret_manager_secret" "kms_wrapper" {
project = local.common_secrets_project_id
secret_id = local.kms_wrapper_secret_name
}
resource "google_secret_manager_secret_iam_member" "kms_wrapper_secret_viewer" {
for_each = local.secret_manager_access_sas
project = local.common_secrets_project_id
secret_id = data.google_secret_manager_secret.kms_wrapper.secret_id
role = "roles/secretmanager.viewer"
member = each.value
}
resource "google_secret_manager_secret_iam_member" "kms_wrapper_secret" {
for_each = local.secret_manager_access_sas
project = local.common_secrets_project_id
secret_id = data.google_secret_manager_secret.kms_wrapper.secret_id
role = "roles/secretmanager.secretAccessor"
member = each.value
}
#################################
# Logging project access
#################################
resource "google_project_iam_member" "log_browser" {
for_each = local.all_projects
project = local.common_logs_project_id
role = "roles/browser"
member = "serviceAccount:${each.value.sa}"
}
resource "google_project_iam_member" "logs_writer" {
for_each = local.all_projects
project = local.common_logs_project_id
role = "roles/logging.logWriter"
member = "serviceAccount:${each.value.sa}"
}
#################################
# KMS project access
#################################
resource "google_project_iam_member" "kms_browser" {
for_each = local.all_projects
project = local.shared_kms_project_id
role = "roles/browser"
member = "serviceAccount:${each.value.sa}"
}
resource "google_project_iam_member" "kms_viewer" {
for_each = local.all_projects
project = local.shared_kms_project_id
role = "roles/cloudkms.viewer"
member = "serviceAccount:${each.value.sa}"
}
##################################
# Common logs bucket access
##################################
// Grant objectCreator role on the common log bucket to the Storage service agent
resource "google_storage_bucket_iam_member" "storage_log_writer" {
bucket = local.logs_export_storage_bucket_name
role = "roles/storage.objectCreator"
member = "serviceAccount:service-${module.ingestion_project.project_number}@gs-project-accounts.iam.gserviceaccount.com"
depends_on = [
time_sleep.wait_for_sa
]
}