diff --git a/README.md b/README.md index 4b7ade21..a1d8d0e1 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ Once you are finished with the reference architecture, you can remove all provis | environment\_type | The environment type to associate the reference architecture with. | `string` | `"development"` | no | | gar\_repository\_id | Google Artifact Registry repository ID. | `string` | `"htc-ref-arch"` | no | | github\_org\_id | GitHub org id (required for Backstage) | `string` | `null` | no | -| humanitec\_org\_id | Humanitec Organization ID (required for Backstage) | `string` | `null` | no | +| humanitec\_org\_id | Humanitec Organization ID. | `string` | `null` | no | | humanitec\_prefix | A prefix that will be attached to all IDs created in Humanitec. | `string` | `"htc-ref-arch-"` | no | | with\_backstage | Deploy Backstage | `bool` | `false` | no | diff --git a/main.tf b/main.tf index 646e555f..444a6b7a 100644 --- a/main.tf +++ b/main.tf @@ -5,6 +5,7 @@ module "base" { project_id = var.project_id region = var.region humanitec_prefix = var.humanitec_prefix + humanitec_org_id = var.humanitec_org_id environment = var.environment environment_type = var.environment_type diff --git a/modules/base/README.md b/modules/base/README.md index d4b132b8..16933fa0 100644 --- a/modules/base/README.md +++ b/modules/base/README.md @@ -17,6 +17,7 @@ | Name | Source | Version | |------|--------|---------| +| credentials | ../dynamic_creds | n/a | | k8s | ../gke | n/a | | network | ../network | n/a | | res\_defs | ../htc_res_defs | n/a | @@ -40,6 +41,7 @@ | gke\_autopilot | Whether GKE Autopilot should be used | `bool` | `true` | no | | gke\_cluster\_name | The name of the GKE Cluster. Must be unique within the project. | `string` | `"htc-ref-arch-cluster"` | no | | gke\_subnet\_name | The name of the subnet to allocate IPs for the GKE Cluster from. If vpc\_subnet is set, this must be updated. | `string` | `"htc-ref-arch-subnet"` | no | +| humanitec\_org\_id | Humanitec Organization ID. | `string` | `null` | no | | humanitec\_prefix | A prefix that will be attached to all IDs created in Humanitec. | `string` | `""` | no | | vpc\_description | VPC Description | `string` | `"VPC for Humanitec Reference Architecture Implementation for GCP. https://github.com/humanitec-architecture/reference-archietcture-gcp"` | no | | vpc\_name | VPC Name | `string` | `"htc-ref-arch-vpc"` | no | diff --git a/modules/base/main.tf b/modules/base/main.tf index 0b52d05d..acd52e8c 100644 --- a/modules/base/main.tf +++ b/modules/base/main.tf @@ -44,17 +44,28 @@ module "k8s" { gar_repository_location = var.gar_repository_location } +# ###################################################################### +# # DYNAMIC CREDENTIALS +# ###################################################################### +module "credentials" { + source = "../dynamic_creds" + humanitec_org = var.humanitec_org_id + gcp_project_id = var.project_id + +} + + # ###################################################################### # # HUMANITEC MODULE # ###################################################################### module "res_defs" { - source = "../htc_res_defs" - k8s_cluster_name = module.k8s.cluster_name - k8s_loadbalancer = module.k8s.loadbalancer - k8s_region = var.region - k8s_project_id = var.project_id - k8s_credentials = module.k8s.credentials - environment = var.environment - environment_type = var.environment_type - prefix = var.humanitec_prefix + source = "../htc_res_defs" + k8s_cluster_name = module.k8s.cluster_name + k8s_loadbalancer = module.k8s.loadbalancer + k8s_region = var.region + k8s_project_id = var.project_id + environment = var.environment + environment_type = var.environment_type + prefix = var.humanitec_prefix + humanitec_cloud_account = module.credentials.humanitec_cloud_account } diff --git a/modules/base/terraform.tfvars.example b/modules/base/terraform.tfvars.example index c3a72d00..e6d708ab 100644 --- a/modules/base/terraform.tfvars.example +++ b/modules/base/terraform.tfvars.example @@ -20,6 +20,9 @@ gke_cluster_name = "htc-ref-arch-cluster" # The name of the subnet to allocate IPs for the GKE Cluster from. If vpc_subnet is set, this must be updated. gke_subnet_name = "htc-ref-arch-subnet" +# Humanitec Organization ID. +humanitec_org_id = "" + # A prefix that will be attached to all IDs created in Humanitec. humanitec_prefix = "" diff --git a/modules/base/variables.tf b/modules/base/variables.tf index f6259d99..6cf131c7 100644 --- a/modules/base/variables.tf +++ b/modules/base/variables.tf @@ -7,12 +7,17 @@ variable "project_id" { description = "GCP Project ID to provision resources in." } - variable "region" { type = string description = "GCP Region to provision resources in." } +variable "humanitec_org_id" { + description = "Humanitec Organization ID." + type = string + default = null +} + ########################################## # OPTIONAL INPUTS ########################################## diff --git a/modules/dynamic_creds/README.md b/modules/dynamic_creds/README.md new file mode 100644 index 00000000..0ad9a682 --- /dev/null +++ b/modules/dynamic_creds/README.md @@ -0,0 +1,44 @@ + +### Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| google | ~> 5.1 | +| humanitec | ~> 1.0 | + +### Providers + +| Name | Version | +|------|---------| +| google | ~> 5.1 | +| humanitec | ~> 1.0 | + +### Resources + +| Name | Type | +|------|------| +| [google_iam_workload_identity_pool.pool](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool) | resource | +| [google_iam_workload_identity_pool_provider.pool_provider](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/iam_workload_identity_pool_provider) | resource | +| [google_project_iam_member.cloud_account_container_role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource | +| [google_service_account.service_account](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource | +| [google_service_account_iam_binding.iam-binding](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_binding) | resource | +| [humanitec_resource_account.cloud_account](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_account) | resource | +| [google_project.project](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/project) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| gcp\_project\_id | The ID of the GCP project to which resources will be deployed. | `string` | n/a | yes | +| humanitec\_org | The identifier of the Humanitec organization used for managing deployments and resources. | `string` | n/a | yes | +| gcp\_service\_account\_id | The ID of the service account used for authenticating and managing GCP resources. | `string` | `"humanitec-cloud-account"` | no | +| gcp\_workload\_identity\_pool\_id | The ID of the Workload Identity Pool in GCP, which allows you to manage resources within the GCP project. | `string` | `"humanitec-wif-pool"` | no | +| gcp\_workload\_identity\_pool\_provider\_id | The ID of the Workload Identity Pool Provider within the specified Workload Identity Pool in GCP, enabling integration with Humanitec. | `string` | `"humanitec-wif"` | no | + +### Outputs + +| Name | Description | +|------|-------------| +| humanitec\_cloud\_account | The ID of the Humanitec Cloud Account. | + \ No newline at end of file diff --git a/modules/dynamic_creds/main.tf b/modules/dynamic_creds/main.tf new file mode 100644 index 00000000..a8562f6f --- /dev/null +++ b/modules/dynamic_creds/main.tf @@ -0,0 +1,51 @@ +data "google_project" "project" { + project_id = var.gcp_project_id +} + +resource "google_iam_workload_identity_pool" "pool" { + workload_identity_pool_id = var.gcp_workload_identity_pool_id + display_name = "Humanitec Identity Pool" + description = "Identity pool for platform orchiestration" +} + +resource "google_iam_workload_identity_pool_provider" "pool_provider" { + workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id + workload_identity_pool_provider_id = var.gcp_workload_identity_pool_provider_id + attribute_mapping = { + "google.subject" = "assertion.sub" + } + oidc { + issuer_uri = "https://idtoken.humanitec.io" + } +} + +resource "google_service_account" "service_account" { + account_id = var.gcp_service_account_id + display_name = "Humanitec GCP dynamic cloud account" + description = "Used by Humanitec Platform Orchestrator Cloud Account" +} + +resource "humanitec_resource_account" "cloud_account" { + id = "humanitec-gcp-dynamic-cloud-account" + name = "Humanitec GCP dynamic cloud account" + type = "gcp-identity" + credentials = jsonencode({ + "gcp_service_account" = "${google_service_account.service_account.account_id}@${var.gcp_project_id}.iam.gserviceaccount.com" + "gcp_audience" = "//iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.pool.workload_identity_pool_id}/providers/${google_iam_workload_identity_pool_provider.pool_provider.workload_identity_pool_provider_id}" + }) +} + +resource "google_service_account_iam_binding" "iam-binding" { + service_account_id = google_service_account.service_account.name + role = "roles/iam.workloadIdentityUser" + + members = [ + "principal://iam.googleapis.com/projects/${data.google_project.project.number}/locations/global/workloadIdentityPools/humanitec-wif-pool/subject/${var.humanitec_org}/${humanitec_resource_account.cloud_account.id}", + ] +} + +resource "google_project_iam_member" "cloud_account_container_role" { + project = var.gcp_project_id + role = "roles/container.admin" + member = "serviceAccount:${google_service_account.service_account.email}" +} diff --git a/modules/dynamic_creds/outputs.tf b/modules/dynamic_creds/outputs.tf new file mode 100644 index 00000000..f488fb8b --- /dev/null +++ b/modules/dynamic_creds/outputs.tf @@ -0,0 +1,4 @@ +output "humanitec_cloud_account" { + value = humanitec_resource_account.cloud_account.id + description = "The ID of the Humanitec Cloud Account." +} diff --git a/modules/dynamic_creds/providers.tf b/modules/dynamic_creds/providers.tf new file mode 100644 index 00000000..9c3aaeed --- /dev/null +++ b/modules/dynamic_creds/providers.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + humanitec = { + source = "humanitec/humanitec" + version = "~> 1.0" + } + google = { + source = "hashicorp/google" + version = "~> 5.1" + } + } + required_version = ">= 1.3.0" +} diff --git a/modules/dynamic_creds/terraform.tfvars.example b/modules/dynamic_creds/terraform.tfvars.example new file mode 100644 index 00000000..d491cf4b --- /dev/null +++ b/modules/dynamic_creds/terraform.tfvars.example @@ -0,0 +1,15 @@ + +# The ID of the GCP project to which resources will be deployed. +gcp_project_id = "" + +# The ID of the service account used for authenticating and managing GCP resources. +gcp_service_account_id = "humanitec-cloud-account" + +# The ID of the Workload Identity Pool in GCP, which allows you to manage resources within the GCP project. +gcp_workload_identity_pool_id = "humanitec-wif-pool" + +# The ID of the Workload Identity Pool Provider within the specified Workload Identity Pool in GCP, enabling integration with Humanitec. +gcp_workload_identity_pool_provider_id = "humanitec-wif" + +# The identifier of the Humanitec organization used for managing deployments and resources. +humanitec_org = "" \ No newline at end of file diff --git a/modules/dynamic_creds/variables.tf b/modules/dynamic_creds/variables.tf new file mode 100644 index 00000000..80ba18ae --- /dev/null +++ b/modules/dynamic_creds/variables.tf @@ -0,0 +1,27 @@ +variable "gcp_project_id" { + type = string + description = "The ID of the GCP project to which resources will be deployed." +} + +variable "gcp_workload_identity_pool_id" { + type = string + default = "humanitec-wif-pool" + description = "The ID of the Workload Identity Pool in GCP, which allows you to manage resources within the GCP project." +} + +variable "gcp_workload_identity_pool_provider_id" { + type = string + default = "humanitec-wif" + description = "The ID of the Workload Identity Pool Provider within the specified Workload Identity Pool in GCP, enabling integration with Humanitec." +} + +variable "gcp_service_account_id" { + type = string + default = "humanitec-cloud-account" + description = "The ID of the service account used for authenticating and managing GCP resources." +} + +variable "humanitec_org" { + type = string + description = "The identifier of the Humanitec organization used for managing deployments and resources." +} diff --git a/modules/github/README.md b/modules/github/README.md index 827d61c8..d515f492 100644 --- a/modules/github/README.md +++ b/modules/github/README.md @@ -45,6 +45,6 @@ | gar\_repository\_location | Location of the Google Artifact Registry repository. | `string` | n/a | yes | | github\_org\_id | GitHub org id | `string` | n/a | yes | | humanitec\_ci\_service\_user\_token | Humanitec CI Service User Token | `string` | n/a | yes | -| humanitec\_org\_id | Humanitec Organization ID | `string` | n/a | yes | +| humanitec\_org\_id | Humanitec Organization ID. | `string` | n/a | yes | | project\_id | GCP Project ID to provision resources in. | `string` | n/a | yes | \ No newline at end of file diff --git a/modules/github/terraform.tfvars.example b/modules/github/terraform.tfvars.example index a3742fe3..07ce19e5 100644 --- a/modules/github/terraform.tfvars.example +++ b/modules/github/terraform.tfvars.example @@ -11,7 +11,7 @@ github_org_id = "" # Humanitec CI Service User Token humanitec_ci_service_user_token = "" -# Humanitec Organization ID +# Humanitec Organization ID. humanitec_org_id = "" # GCP Project ID to provision resources in. diff --git a/modules/github/variables.tf b/modules/github/variables.tf index 1662000a..e7e0a194 100644 --- a/modules/github/variables.tf +++ b/modules/github/variables.tf @@ -14,7 +14,7 @@ variable "gar_repository_location" { } variable "humanitec_org_id" { - description = "Humanitec Organization ID" + description = "Humanitec Organization ID." type = string validation { diff --git a/modules/htc_res_defs/README.md b/modules/htc_res_defs/README.md index 0869366e..9f6a0f89 100644 --- a/modules/htc_res_defs/README.md +++ b/modules/htc_res_defs/README.md @@ -23,7 +23,6 @@ | Name | Type | |------|------| -| [humanitec_resource_account.cluster_account](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_account) | resource | | [humanitec_resource_definition.k8s_cluster](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | | [humanitec_resource_definition.k8s_namespace](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | | [humanitec_resource_definition_criteria.default_mysql](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | @@ -37,8 +36,8 @@ |------|-------------|------|---------|:--------:| | environment | The environment to use for matching criteria. | `string` | n/a | yes | | environment\_type | The environment type to use for matching criteria. | `string` | n/a | yes | +| humanitec\_cloud\_account | The ID of the Humanitec Cloud Account. | `string` | n/a | yes | | k8s\_cluster\_name | The name of the cluster. | `string` | n/a | yes | -| k8s\_credentials | The credentials used to establish a connection to the cluster. | `string` | n/a | yes | | k8s\_loadbalancer | IP address or Host of the load balancer used by the ingress controller. | `string` | n/a | yes | | k8s\_project\_id | The GCP Project the cluster is in. | `string` | n/a | yes | | k8s\_region | The region the cluster is in. | `string` | n/a | yes | diff --git a/modules/htc_res_defs/main.tf b/modules/htc_res_defs/main.tf index 23d75c6e..02855670 100644 --- a/modules/htc_res_defs/main.tf +++ b/modules/htc_res_defs/main.tf @@ -1,18 +1,10 @@ -resource "humanitec_resource_account" "cluster_account" { - id = "${var.prefix}cluster" - name = "${var.prefix}cluster" - type = "gcp" - - credentials = var.k8s_credentials -} - resource "humanitec_resource_definition" "k8s_cluster" { driver_type = "humanitec/k8s-cluster-gke" id = "${var.prefix}cluster" name = "${var.prefix}cluster" type = "k8s-cluster" - driver_account = humanitec_resource_account.cluster_account.id + driver_account = var.humanitec_cloud_account driver_inputs = { values_string = jsonencode({ "name" = var.k8s_cluster_name diff --git a/modules/htc_res_defs/terraform.tfvars.example b/modules/htc_res_defs/terraform.tfvars.example index 2600a8f6..5c38b0b5 100644 --- a/modules/htc_res_defs/terraform.tfvars.example +++ b/modules/htc_res_defs/terraform.tfvars.example @@ -5,12 +5,12 @@ environment = "" # The environment type to use for matching criteria. environment_type = "" +# The ID of the Humanitec Cloud Account. +humanitec_cloud_account = "" + # The name of the cluster. k8s_cluster_name = "" -# The credentials used to establish a connection to the cluster. -k8s_credentials = "" - # IP address or Host of the load balancer used by the ingress controller. k8s_loadbalancer = "" diff --git a/modules/htc_res_defs/variables.tf b/modules/htc_res_defs/variables.tf index 94fcebac..4c9c6508 100644 --- a/modules/htc_res_defs/variables.tf +++ b/modules/htc_res_defs/variables.tf @@ -1,4 +1,3 @@ - variable "k8s_cluster_name" { type = string description = "The name of the cluster." @@ -15,10 +14,7 @@ variable "k8s_region" { type = string description = "The region the cluster is in." } -variable "k8s_credentials" { - type = string - description = "The credentials used to establish a connection to the cluster." -} + variable "environment" { type = string description = "The environment to use for matching criteria." @@ -32,3 +28,8 @@ variable "prefix" { description = "A prefix that will be attached to all IDs created in Humanitec." default = "" } + +variable "humanitec_cloud_account" { + type = string + description = "The ID of the Humanitec Cloud Account." +} diff --git a/modules/network/output.tf b/modules/network/outputs.tf similarity index 100% rename from modules/network/output.tf rename to modules/network/outputs.tf diff --git a/terraform.tfvars.example b/terraform.tfvars.example index 6faf1128..8ba806dc 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -14,7 +14,7 @@ gar_repository_location = "" # GitHub org id (required for Backstage) github_org_id = "" -# Humanitec Organization ID (required for Backstage) +# Humanitec Organization ID. humanitec_org_id = "" # A prefix that will be attached to all IDs created in Humanitec. diff --git a/variables.tf b/variables.tf index 5cb5359a..c59133d4 100644 --- a/variables.tf +++ b/variables.tf @@ -59,7 +59,7 @@ variable "github_org_id" { } variable "humanitec_org_id" { - description = "Humanitec Organization ID (required for Backstage)" + description = "Humanitec Organization ID." type = string default = null }