diff --git a/examples/gcp/vendor-access/main.tf b/examples/gcp/vendor-access/main.tf new file mode 100644 index 0000000..bf071fc --- /dev/null +++ b/examples/gcp/vendor-access/main.tf @@ -0,0 +1,17 @@ +# Grant access +module "sn_managed_cloud" { + source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.8.0" + project = "" +} + +# Grant access when using shared vpc +module "sn_managed_cloud_shared_vpc" { + source = "github.com/streamnative/terraform-managed-cloud//modules/gcp/vendor-access?ref=v3.8.0" + project = "" + project_num = "" + network_project = "" + shared_vpc_subnets = [{ + name = "" + region = "" + }] +} diff --git a/modules/gcp/vendor-access/README.md b/modules/gcp/vendor-access/README.md index 35a72c9..84a2c13 100644 --- a/modules/gcp/vendor-access/README.md +++ b/modules/gcp/vendor-access/README.md @@ -492,6 +492,9 @@ After [authenticating to your GCP account](https://registry.terraform.io/provide

+### Examples +More examples of the modules can be found in the `examples/gcp/vendor-access` directory. + ## Terraform Docs ### Requirements @@ -514,6 +517,8 @@ No modules. | Name | Type | |------|------| +| [google_compute_subnetwork_iam_member.network_user](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_subnetwork_iam_member) | resource | +| [google_project_iam_member.service_agent_user](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource | | [google_project_iam_member.sn_access](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource | | [google_project_service.gcp_apis](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_service) | resource | @@ -522,8 +527,11 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [extra\_google\_services](#input\_extra\_google\_services) | Extra google API services need to be enabled. | `list(string)` | `[]` | no | -| [project](#input\_project) | The project id of the target project | `string` | n/a | yes | +| [network\_project](#input\_network\_project) | The project id of the network host project. | `string` | `""` | no | +| [project](#input\_project) | The project id of the target project. | `string` | n/a | yes | +| [project\_num](#input\_project\_num) | The project number of the target project, required when configuring network project. | `string` | `""` | no | | [roles](#input\_roles) | The role list will be associated with StreamNative GSA. | `list(string)` |
[
"roles/editor",
"roles/compute.admin",
"roles/compute.loadBalancerAdmin",
"roles/compute.networkAdmin",
"roles/container.admin",
"roles/dns.admin",
"roles/storage.admin",
"roles/iam.serviceAccountAdmin",
"roles/iam.workloadIdentityPoolAdmin",
"roles/resourcemanager.projectIamAdmin"
]
| no | +| [shared\_vpc\_subnets](#input\_shared\_vpc\_subnets) | The subnet list shared by network host project. |
list(object({
region = string
name = string
}))
| `[]` | no | | [streamnative\_support\_access\_gsa](#input\_streamnative\_support\_access\_gsa) | The GSA will be used by StreamnNative support team. | `list(string)` |
[
"cloud-support-general@sncloud-production.iam.gserviceaccount.com"
]
| no | | [streamnative\_vendor\_access\_gsa](#input\_streamnative\_vendor\_access\_gsa) | The GSA will be used by StreamnNative cloud. | `list(string)` |
[
"cloud-manager@sncloud-production.iam.gserviceaccount.com",
"pool-automation@sncloud-production.iam.gserviceaccount.com"
]
| no | diff --git a/modules/gcp/vendor-access/common.tf b/modules/gcp/vendor-access/common.tf index 095eec8..6255156 100644 --- a/modules/gcp/vendor-access/common.tf +++ b/modules/gcp/vendor-access/common.tf @@ -1,6 +1,27 @@ variable "project" { type = string - description = "The project id of the target project" + description = "The project id of the target project." +} + +variable "project_num" { + type = string + default = "" + description = "The project number of the target project, required when configuring network project." +} + +variable "network_project" { + type = string + default = "" + description = "The project id of the network host project." +} + +variable "shared_vpc_subnets" { + type = list(object({ + region = string + name = string + })) + default = [] + description = "The subnet list shared by network host project." } variable "roles" { diff --git a/modules/gcp/vendor-access/main.tf b/modules/gcp/vendor-access/main.tf index 7a64a15..b542e74 100644 --- a/modules/gcp/vendor-access/main.tf +++ b/modules/gcp/vendor-access/main.tf @@ -1,10 +1,10 @@ locals { - streamnative_gsa = concat(var.streamnative_vendor_access_gsa, var.streamnative_support_access_gsa) + streamnative_gsa = formatlist("serviceAccount:%s", 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), + member : gsa, } ] ]) @@ -31,23 +31,58 @@ resource "google_project_service" "gcp_apis" { service = local.google_services[count.index] } -resource "google_project_iam_member" "sn_access" { +# resource "google_project_iam_member" "sn_access" { +# for_each = { +# for index, binding in local.iam_bindings : +# index => binding +# } +# project = var.project +# role = each.value.role +# member = each.value.member +# depends_on = [google_project_service.gcp_apis] +# } + +locals { + comput_network_user_gsa = var.network_project != "" ? concat(local.streamnative_gsa, [format("serviceAccount:%s@cloudservices.gserviceaccount.com", var.project_num)]) : [] + container_host_service_agent_user = var.network_project != "" ? [format("serviceAccount:service-%s@container-engine-robot.iam.gserviceaccount.com", var.project_num)] : [] + comput_network_user_iam_binding = flatten([ + for subnet in var.shared_vpc_subnets : [ + for gsa in concat(local.comput_network_user_gsa, local.container_host_service_agent_user) : { + region : subnet.region, + subnet : subnet.name, + member : gsa, + } + ] + ]) +} + +resource "google_compute_subnetwork_iam_member" "network_user" { for_each = { - for index, binding in local.iam_bindings : + for index, binding in local.comput_network_user_iam_binding : index => binding } - project = var.project - role = each.value.role + project = var.network_project + region = each.value.region + subnetwork = each.value.subnet + role = "roles/compute.networkUser" member = each.value.member depends_on = [google_project_service.gcp_apis] } +resource "google_project_iam_member" "service_agent_user" { + count = length(local.container_host_service_agent_user) + project = var.network_project + role = "roles/container.hostServiceAgentUser" + member = local.container_host_service_agent_user[count.index] + depends_on = [google_project_service.gcp_apis] +} + 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." }