|
| 1 | +locals { |
| 2 | + streamnative_gsa = distinct(var.streamnative_vendor_access_gsa) |
| 3 | + cluster_projects = distinct(var.cluster_projects) |
| 4 | + buckets_list = distinct([for item in var.buckets : "${split("/", item)[0]}"]) |
| 5 | + buckets_path = distinct([for item in var.buckets : "${replace(item, "/(\\/|\\/\\*)+$/", "")}"]) |
| 6 | +} |
| 7 | + |
| 8 | +# Grant permissions to the project service account that will be impersonated by StreamNative Control Plane service account |
| 9 | +locals { |
| 10 | + impersonation_roles = [ |
| 11 | + "roles/storage.objectUser", |
| 12 | + "roles/storage.objectViewer", |
| 13 | + ] |
| 14 | + impersonation_iam_bindings = flatten([ |
| 15 | + for role in local.impersonation_roles : [ |
| 16 | + for bucket_path in local.buckets_path : { |
| 17 | + bucket : split("/", bucket_path)[0], |
| 18 | + role : role, |
| 19 | + expression : role == "roles/storage.objectViewer" ? "" : (length(split("/", bucket_path)) == 1 ? format("resource.name.startsWith(\"projects/_/buckets/%s/objects\")", split("/", bucket_path)[0]) : format("resource.name.startsWith(\"projects/_/buckets/%s/objects/%s/\")", split("/", bucket_path)[0], join("/", slice(split("/", bucket_path), 1, length(split("/", bucket_path)))))) |
| 20 | + } |
| 21 | + ] |
| 22 | + ]) |
| 23 | + |
| 24 | +} |
| 25 | +resource "google_service_account" "gsa" { |
| 26 | + account_id = var.account_id |
| 27 | + project = var.project |
| 28 | + display_name = "StreamNative Cloud Control Plane access bucket service account." |
| 29 | +} |
| 30 | + |
| 31 | +resource "google_storage_bucket_iam_member" "gcs" { |
| 32 | + count = length(local.impersonation_iam_bindings) |
| 33 | + bucket = local.impersonation_iam_bindings[count.index].bucket |
| 34 | + role = local.impersonation_iam_bindings[count.index].role |
| 35 | + member = "serviceAccount:${google_service_account.gsa.email}" |
| 36 | + |
| 37 | + condition { |
| 38 | + title = "restrict_to_data_path" |
| 39 | + description = "Restrict gcs access" |
| 40 | + expression = local.impersonation_iam_bindings[count.index].expression |
| 41 | + } |
| 42 | + |
| 43 | + depends_on = [google_service_account.gsa] |
| 44 | +} |
| 45 | + |
| 46 | +resource "google_service_account_iam_member" "sn_control_plane" { |
| 47 | + count = length(local.streamnative_gsa) |
| 48 | + service_account_id = google_service_account.gsa.id |
| 49 | + role = "roles/iam.serviceAccountTokenCreator" |
| 50 | + member = "serviceAccount:${local.streamnative_gsa[count.index]}" |
| 51 | + depends_on = [google_service_account.gsa] |
| 52 | +} |
| 53 | + |
| 54 | +data "google_project" "project" { |
| 55 | + count = length(local.cluster_projects) |
| 56 | + project_id = local.cluster_projects[count.index] |
| 57 | +} |
| 58 | + |
| 59 | +resource "google_service_account_iam_member" "sn_data_plane" { |
| 60 | + count = length(local.cluster_projects) |
| 61 | + service_account_id = google_service_account.gsa.id |
| 62 | + role = "roles/iam.workloadIdentityUser" |
| 63 | + member = "principalSet://iam.googleapis.com/projects/${data.google_project.project[count.index].number}/locations/global/workloadIdentityPools/${local.cluster_projects[count.index]}.svc.id.goog/namespace/${var.streamnative_org_id}" |
| 64 | + depends_on = [google_service_account.gsa] |
| 65 | + |
| 66 | +} |
| 67 | + |
| 68 | +output "google_service_account" { |
| 69 | + value = google_service_account.gsa |
| 70 | + description = "Google Service Account for Access GCS Bucket" |
| 71 | + depends_on = [google_service_account.gsa] |
| 72 | +} |
0 commit comments