Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support GCP impersonation #94

Merged
merged 7 commits into from
Jul 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions modules/gcp/vendor-access/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ provider "google" {
}

module "sn_managed_cloud" {
source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.7.0"
source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.15.0"
project = "<YOUR_PROJECT>"
streamnative_org_id = "<YOUR_ORG_ID>"
}
```

Expand Down Expand Up @@ -523,7 +524,8 @@ No modules.
|------|-------------|------|---------|:--------:|
| <a name="input_extra_google_services"></a> [extra\_google\_services](#input\_extra\_google\_services) | Extra google API services need to be enabled. | `list(string)` | `[]` | no |
| <a name="input_project"></a> [project](#input\_project) | The project id of the target project | `string` | n/a | yes |
| <a name="input_roles"></a> [roles](#input\_roles) | The role list will be associated with StreamNative GSA. | `list(string)` | <pre>[<br> "roles/editor",<br> "roles/compute.admin",<br> "roles/compute.loadBalancerAdmin",<br> "roles/compute.networkAdmin",<br> "roles/container.admin",<br> "roles/dns.admin",<br> "roles/storage.admin",<br> "roles/iam.serviceAccountAdmin",<br> "roles/iam.workloadIdentityPoolAdmin",<br> "roles/resourcemanager.projectIamAdmin"<br>]</pre> | no |
| <a name="input_roles"></a> [roles](#input\_roles) | The role list will be associated with StreamNative GSA. | `list(string)` | <pre>[<br> "roles/editor",<br> "roles/cloudkms.admin",<br> "roles/compute.admin",<br> "roles/compute.loadBalancerAdmin",<br> "roles/compute.networkAdmin",<br> "roles/container.admin",<br> "roles/dns.admin",<br> "roles/storage.admin",<br> "roles/iam.serviceAccountAdmin",<br> "roles/iam.workloadIdentityPoolAdmin",<br> "roles/resourcemanager.projectIamAdmin"<br>]</pre> | no |
| <a name="input_streamnative_org_id"></a> [streamnative\_org\_id](#input\_streamnative\_org\_id) | Your Organization ID within StreamNative Cloud, used as name of impersonation GSA in your project. This will be the organization ID in the StreamNative console, e.g. "o-xhopj". | `string` | `""` | no |
| <a name="input_streamnative_support_access_gsa"></a> [streamnative\_support\_access\_gsa](#input\_streamnative\_support\_access\_gsa) | The GSA will be used by StreamnNative support team. | `list(string)` | <pre>[<br> "cloud-support-general@sncloud-production.iam.gserviceaccount.com"<br>]</pre> | no |
| <a name="input_streamnative_vendor_access_gsa"></a> [streamnative\_vendor\_access\_gsa](#input\_streamnative\_vendor\_access\_gsa) | The GSA will be used by StreamnNative cloud. | `list(string)` | <pre>[<br> "cloud-manager@sncloud-production.iam.gserviceaccount.com",<br> "pool-automation@sncloud-production.iam.gserviceaccount.com"<br>]</pre> | no |

Expand All @@ -533,3 +535,4 @@ No modules.
|------|-------------|
| <a name="output_google_services"></a> [google\_services](#output\_google\_services) | Enabled google services. |
| <a name="output_iam_bindings"></a> [iam\_bindings](#output\_iam\_bindings) | Configured iam policies. |
| <a name="output_impersonation_iam_bindings"></a> [impersonation\_iam\_bindings](#output\_impersonation\_iam\_bindings) | Configured iam policies for impersonation. |
10 changes: 10 additions & 0 deletions modules/gcp/vendor-access/common.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ variable "streamnative_vendor_access_gsa" {
description = "The GSA will be used by StreamnNative cloud."
}

variable "streamnative_org_id" {
default = ""
type = string
description = "Your Organization ID within StreamNative Cloud, used as name of impersonation GSA in your project. This will be the organization ID in the StreamNative console, e.g. \"o-xhopj\"."
validation {
condition = length(var.streamnative_org_id) <= 18
error_message = "The organization ID must not exceed 18 characters. If you reach this limit, please contact StreamNative support."
}
}

variable "streamnative_support_access_gsa" {
default = ["cloud-support-general@sncloud-production.iam.gserviceaccount.com"]
type = list(string)
Expand Down
3 changes: 2 additions & 1 deletion modules/gcp/vendor-access/docs/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ provider "google" {
}

module "sn_managed_cloud" {
source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.7.0"
source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.15.0"
project = "<YOUR_PROJECT>"
streamnative_org_id = "<YOUR_ORG_ID>"
}
88 changes: 71 additions & 17 deletions modules/gcp/vendor-access/main.tf
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
locals {
streamnative_gsa = concat(var.streamnative_vendor_access_gsa, var.streamnative_support_access_gsa)
iam_bindings = flatten([
for role in var.roles : [
for gsa in local.streamnative_gsa : {
role : role,
member : format("serviceAccount:%s", gsa),
}
]
])
google_services = concat([
"autoscaling.googleapis.com",
"cloudresourcemanager.googleapis.com",
Expand All @@ -31,23 +22,86 @@ resource "google_project_service" "gcp_apis" {
service = local.google_services[count.index]
}

locals {
is_impersonation_enabled = var.streamnative_org_id != ""
streamnative_gsa = concat(var.streamnative_vendor_access_gsa, var.streamnative_support_access_gsa)
}

# Grant permissions directly to the StreamNative Cloud service account
locals {
iam_bindings = local.is_impersonation_enabled ? [] : flatten([
for role in var.roles : [
for gsa in local.streamnative_gsa : {
role : role,
member : format("serviceAccount:%s", gsa),
}
]
])
}

resource "google_project_iam_member" "sn_access" {
for_each = {
for index, binding in local.iam_bindings :
index => binding
}
count = length(local.iam_bindings)
project = var.project
role = each.value.role
member = each.value.member
role = local.iam_bindings[count.index].role
member = local.iam_bindings[count.index].member
depends_on = [google_project_service.gcp_apis]
}

# Grant permissions to the project service account that will be impersonated by StreamNative Cloud service account
locals {
streamnative_bootstrap_gsa_name = format("snbootstrap-%s", var.streamnative_org_id)
maxsxu marked this conversation as resolved.
Show resolved Hide resolved
streamnative_bootstrap_roles = local.is_impersonation_enabled ? var.roles : []
impersonation_roles = [
"roles/iam.serviceAccountUser",
"roles/iam.serviceAccountAdmin",
"roles/iam.serviceAccountTokenCreator",
]
impersonation_iam_bindings = local.is_impersonation_enabled ? flatten([
for role in local.impersonation_roles : [
for gsa in local.streamnative_gsa : {
role : role,
member : format("serviceAccount:%s", gsa),
}
]
]) : []

}
resource "google_service_account" "sn_bootstrap" {
count = local.is_impersonation_enabled ? 1 : 0
account_id = local.streamnative_bootstrap_gsa_name
project = var.project
display_name = "StreamNative Bootstrap GSA that will be impersonated by StreamNative Cloud Control Plane."
depends_on = [google_project_service.gcp_apis]
}

resource "google_project_iam_member" "sn_bootstrap" {
count = length(local.streamnative_bootstrap_roles)
project = var.project
role = local.streamnative_bootstrap_roles[count.index]
member = format("serviceAccount:%s", google_service_account.sn_bootstrap[0].email)
depends_on = [google_service_account.sn_bootstrap]
}

resource "google_service_account_iam_member" "sn_bootstrap_impersonation" {
count = length(local.impersonation_iam_bindings)
service_account_id = google_service_account.sn_bootstrap[0].id
role = local.impersonation_iam_bindings[count.index].role
member = local.impersonation_iam_bindings[count.index].member
depends_on = [google_service_account.sn_bootstrap]
}


output "google_services" {
value = local.google_services
value = local.google_services
description = "Enabled google services."
}

output "iam_bindings" {
value = local.iam_bindings
value = local.iam_bindings
description = "Configured iam policies."
}

output "impersonation_iam_bindings" {
value = local.impersonation_iam_bindings
description = "Configured iam policies for impersonation."
}
Loading