From c6b935bf6f8c1c10e8e315a052d198e4234f24ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Thu, 21 Dec 2023 23:34:03 +0100 Subject: [PATCH] feat: gcs resource --- README.md | 1 + examples/gcs/README.md | 72 +++++++++ examples/gcs/main.tf | 153 ++++++++++++++++++ examples/gcs/providers.tf | 12 ++ examples/gcs/terraform.tfvars.example | 20 +++ examples/gcs/variables.tf | 37 +++++ .../gcp-service-account/workload/README.md | 37 +++++ .../gcp-service-account/workload/main.tf | 37 +++++ .../gcp-service-account/workload/outputs.tf | 3 + .../gcp-service-account/workload/providers.tf | 10 ++ .../workload/terraform.tfvars.example | 17 ++ .../gcp-service-account/workload/variables.tf | 31 ++++ humanitec-resource-defs/gcs/basic/README.md | 39 +++++ humanitec-resource-defs/gcs/basic/main.tf | 35 ++++ humanitec-resource-defs/gcs/basic/outputs.tf | 3 + .../gcs/basic/providers.tf | 10 ++ .../gcs/basic/terraform.tfvars.example | 24 +++ .../gcs/basic/variables.tf | 43 +++++ .../gcs/passthrough/README.md | 34 ++++ .../gcs/passthrough/main.tf | 23 +++ .../gcs/passthrough/outputs.tf | 3 + .../gcs/passthrough/providers.tf | 10 ++ .../gcs/passthrough/terraform.tfvars.example | 3 + .../gcs/passthrough/variables.tf | 11 ++ .../iam-role-binding/gcs/README.md | 35 ++++ .../iam-role-binding/gcs/main.tf | 23 +++ .../iam-role-binding/gcs/outputs.tf | 3 + .../iam-role-binding/gcs/providers.tf | 10 ++ .../gcs/terraform.tfvars.example | 11 ++ .../iam-role-binding/gcs/variables.tf | 18 +++ .../k8s/service-account/README.md | 32 ++++ .../k8s/service-account/main.tf | 39 +++++ .../k8s/service-account/outputs.tf | 3 + .../k8s/service-account/providers.tf | 10 ++ .../service-account/terraform.tfvars.example | 1 + .../k8s/service-account/variables.tf | 4 + .../workload/service-account/README.md | 32 ++++ .../workload/service-account/main.tf | 21 +++ .../workload/service-account/outputs.tf | 3 + .../workload/service-account/providers.tf | 10 ++ .../service-account/terraform.tfvars.example | 1 + .../workload/service-account/variables.tf | 4 + .../gcp-service-account/workload/README.md | 44 +++++ .../gcp-service-account/workload/bindings.tf | 14 ++ modules/gcp-service-account/workload/main.tf | 22 +++ .../gcp-service-account/workload/outputs.tf | 7 + .../gcp-service-account/workload/providers.tf | 23 +++ .../workload/terraform.tfvars.example | 22 +++ .../gcp-service-account/workload/variables.tf | 40 +++++ modules/gcs/basic/README.md | 40 +++++ modules/gcs/basic/main.tf | 16 ++ modules/gcs/basic/outputs.tf | 3 + modules/gcs/basic/providers.tf | 22 +++ modules/gcs/basic/terraform.tfvars.example | 20 +++ modules/gcs/basic/variables.tf | 41 +++++ 55 files changed, 1242 insertions(+) create mode 100644 examples/gcs/README.md create mode 100644 examples/gcs/main.tf create mode 100644 examples/gcs/providers.tf create mode 100644 examples/gcs/terraform.tfvars.example create mode 100644 examples/gcs/variables.tf create mode 100644 humanitec-resource-defs/gcp-service-account/workload/README.md create mode 100644 humanitec-resource-defs/gcp-service-account/workload/main.tf create mode 100644 humanitec-resource-defs/gcp-service-account/workload/outputs.tf create mode 100644 humanitec-resource-defs/gcp-service-account/workload/providers.tf create mode 100644 humanitec-resource-defs/gcp-service-account/workload/terraform.tfvars.example create mode 100644 humanitec-resource-defs/gcp-service-account/workload/variables.tf create mode 100644 humanitec-resource-defs/gcs/basic/README.md create mode 100644 humanitec-resource-defs/gcs/basic/main.tf create mode 100644 humanitec-resource-defs/gcs/basic/outputs.tf create mode 100644 humanitec-resource-defs/gcs/basic/providers.tf create mode 100644 humanitec-resource-defs/gcs/basic/terraform.tfvars.example create mode 100644 humanitec-resource-defs/gcs/basic/variables.tf create mode 100644 humanitec-resource-defs/gcs/passthrough/README.md create mode 100644 humanitec-resource-defs/gcs/passthrough/main.tf create mode 100644 humanitec-resource-defs/gcs/passthrough/outputs.tf create mode 100644 humanitec-resource-defs/gcs/passthrough/providers.tf create mode 100644 humanitec-resource-defs/gcs/passthrough/terraform.tfvars.example create mode 100644 humanitec-resource-defs/gcs/passthrough/variables.tf create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/README.md create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/main.tf create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/outputs.tf create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/providers.tf create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/terraform.tfvars.example create mode 100644 humanitec-resource-defs/iam-role-binding/gcs/variables.tf create mode 100644 humanitec-resource-defs/k8s/service-account/README.md create mode 100644 humanitec-resource-defs/k8s/service-account/main.tf create mode 100644 humanitec-resource-defs/k8s/service-account/outputs.tf create mode 100644 humanitec-resource-defs/k8s/service-account/providers.tf create mode 100644 humanitec-resource-defs/k8s/service-account/terraform.tfvars.example create mode 100644 humanitec-resource-defs/k8s/service-account/variables.tf create mode 100644 humanitec-resource-defs/workload/service-account/README.md create mode 100644 humanitec-resource-defs/workload/service-account/main.tf create mode 100644 humanitec-resource-defs/workload/service-account/outputs.tf create mode 100644 humanitec-resource-defs/workload/service-account/providers.tf create mode 100644 humanitec-resource-defs/workload/service-account/terraform.tfvars.example create mode 100644 humanitec-resource-defs/workload/service-account/variables.tf create mode 100644 modules/gcp-service-account/workload/README.md create mode 100644 modules/gcp-service-account/workload/bindings.tf create mode 100644 modules/gcp-service-account/workload/main.tf create mode 100644 modules/gcp-service-account/workload/outputs.tf create mode 100644 modules/gcp-service-account/workload/providers.tf create mode 100644 modules/gcp-service-account/workload/terraform.tfvars.example create mode 100644 modules/gcp-service-account/workload/variables.tf create mode 100644 modules/gcs/basic/README.md create mode 100644 modules/gcs/basic/main.tf create mode 100644 modules/gcs/basic/outputs.tf create mode 100644 modules/gcs/basic/providers.tf create mode 100644 modules/gcs/basic/terraform.tfvars.example create mode 100644 modules/gcs/basic/variables.tf diff --git a/README.md b/README.md index 048508b..2ea7e09 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ A collection of GCP resources ready to be used with [Humanitec](https://humanite The following resources are included: * [dns/basic](./humanitec-resource-defs/dns/basic): GCP Cloud DNS `dns` resource. +* [gcs/basic](./humanitec-resource-defs/gcs/basic): A basic cloud storage bucket. * [redis/basic](./humanitec-resource-defs/redis/basic): GCP Memorystore `redis` resource. The `humanitec-resource-defs` directory includes the respective resource definitions. diff --git a/examples/gcs/README.md b/examples/gcs/README.md new file mode 100644 index 0000000..e0ca30a --- /dev/null +++ b/examples/gcs/README.md @@ -0,0 +1,72 @@ +# Example: gcs resource based on Google Cloud Storage + +This example configures a [gcs](https://developer.humanitec.com/platform-orchestrator/reference/resource-types/#gcs) Resource Definition using Google Cloud Storage, with two different access policies: + +* `basic-admin` (full access) +* `basic-read-only` (read-only access) + +Those Resource Definitions can be used in your Score file using: + +```yaml +resources: + ... + gcs: + type: gcs + class: basic-admin +``` + +The workload service account will automatically be assigned the necessary GCP Service Account with the selected role bindings. + + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| gcp\_service\_account\_workload | ../../humanitec-resource-defs/gcp-service-account/workload | n/a | +| gcs\_basic | ../../humanitec-resource-defs/gcs/basic | n/a | +| gcs\_basic\_admin | ../../humanitec-resource-defs/gcs/passthrough | n/a | +| gcs\_basic\_read\_only | ../../humanitec-resource-defs/gcs/passthrough | n/a | +| iam\_role\_binding\_gcs\_admin | ../../humanitec-resource-defs/iam-role-binding/gcs | n/a | +| iam\_role\_binding\_gcs\_read\_only | ../../humanitec-resource-defs/iam-role-binding/gcs | n/a | +| k8s\_service\_account | ../../humanitec-resource-defs/k8s/service-account | n/a | +| workload | ../../humanitec-resource-defs/workload/service-account | n/a | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_application.example](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/application) | resource | +| [humanitec_resource_definition_criteria.gcp_service_account_workload](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.gcs_basic](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.gcs_basic_admin](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.gcs_basic_read_only](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.iam_role_binding_gcs_admin](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.iam_role_binding_gcs_read_only](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.k8s_service_account](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | +| [humanitec_resource_definition_criteria.workload](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| credentials | GCP credentials | `string` | n/a | yes | +| location | The location of the bucket | `string` | n/a | yes | +| project | GCP project ID | `string` | n/a | yes | +| name | Name of the example application | `string` | `"hum-rp-gcs-example"` | no | +| prefix | n/a | `string` | `"hum-rp-gcs-ex-"` | no | +| resource\_packs\_gcp\_rev | GCP Resource Pack git ref | `string` | `"refs/heads/main"` | no | +| resource\_packs\_gcp\_url | GCP Resource Pack git url | `string` | `"https://github.com/humanitec-architecture/resource-packs-gcp.git"` | no | + diff --git a/examples/gcs/main.tf b/examples/gcs/main.tf new file mode 100644 index 0000000..1531a2f --- /dev/null +++ b/examples/gcs/main.tf @@ -0,0 +1,153 @@ +resource "humanitec_application" "example" { + id = var.name + name = var.name +} + +# GCS bucket + +locals { + # Classes used to build the resource definition graph + gcs_basic_class = "basic" + gcs_admin_policy_class = "gcs-basic-admin" + gcs_read_only_policy_class = "gcs-basic-read-only" + + # Classes that developers can select from + gcs_basic_admin_class = "basic-admin" + gcs_basic_read_only_class = "basic-read-only" +} + + +module "gcs_basic" { + source = "../../humanitec-resource-defs/gcs/basic" + + resource_packs_gcp_url = var.resource_packs_gcp_url + resource_packs_gcp_rev = var.resource_packs_gcp_rev + + project = var.project + credentials = var.credentials + force_destroy = true + location = var.location + + prefix = var.prefix +} + +resource "humanitec_resource_definition_criteria" "gcs_basic" { + resource_definition_id = module.gcs_basic.id + app_id = humanitec_application.example.id + class = local.gcs_basic_class +} + +# Add different access policy to gcs basic bucket + +# Admin + +## Policy + +module "iam_role_binding_gcs_admin" { + source = "../../humanitec-resource-defs/iam-role-binding/gcs" + + prefix = var.prefix + + gcs_resource_class = local.gcs_basic_class + name = "admin" + role = "roles/storage.admin" +} + +resource "humanitec_resource_definition_criteria" "iam_role_binding_gcs_admin" { + resource_definition_id = module.iam_role_binding_gcs_admin.id + app_id = humanitec_application.example.id + class = local.gcs_admin_policy_class +} + +## Exposed passthrough resource definition +module "gcs_basic_admin" { + source = "../../humanitec-resource-defs/gcs/passthrough" + + prefix = var.prefix + + gcs_resource_class = local.gcs_basic_class + policy_resource_class = local.gcs_admin_policy_class +} + +resource "humanitec_resource_definition_criteria" "gcs_basic_admin" { + resource_definition_id = module.gcs_basic_admin.id + app_id = humanitec_application.example.id + class = local.gcs_basic_admin_class +} + +# Read-only + +## Policy + +module "iam_role_binding_gcs_read_only" { + source = "../../humanitec-resource-defs/iam-role-binding/gcs" + + prefix = var.prefix + + gcs_resource_class = local.gcs_basic_class + name = "read-only" + role = "roles/storage.objectViewer" +} + +resource "humanitec_resource_definition_criteria" "iam_role_binding_gcs_read_only" { + resource_definition_id = module.iam_role_binding_gcs_read_only.id + app_id = humanitec_application.example.id + class = local.gcs_read_only_policy_class +} + +## Exposed passthrough resource definition +module "gcs_basic_read_only" { + source = "../../humanitec-resource-defs/gcs/passthrough" + + prefix = var.prefix + + gcs_resource_class = local.gcs_basic_class + policy_resource_class = local.gcs_read_only_policy_class +} + +resource "humanitec_resource_definition_criteria" "gcs_basic_read_only" { + resource_definition_id = module.gcs_basic_read_only.id + app_id = humanitec_application.example.id + class = local.gcs_basic_read_only_class +} + +# Required resources for workload identity + + +module "k8s_service_account" { + source = "../../humanitec-resource-defs/k8s/service-account" + + prefix = var.prefix +} + +resource "humanitec_resource_definition_criteria" "k8s_service_account" { + resource_definition_id = module.k8s_service_account.id + app_id = humanitec_application.example.id +} + +module "gcp_service_account_workload" { + source = "../../humanitec-resource-defs/gcp-service-account/workload" + + resource_packs_gcp_url = var.resource_packs_gcp_url + resource_packs_gcp_rev = var.resource_packs_gcp_rev + + project = var.project + credentials = var.credentials + prefix = var.prefix +} + +resource "humanitec_resource_definition_criteria" "gcp_service_account_workload" { + resource_definition_id = module.gcp_service_account_workload.id + app_id = humanitec_application.example.id +} + +module "workload" { + source = "../../humanitec-resource-defs/workload/service-account" + + prefix = var.prefix +} + +resource "humanitec_resource_definition_criteria" "workload" { + resource_definition_id = module.workload.id + app_id = humanitec_application.example.id +} diff --git a/examples/gcs/providers.tf b/examples/gcs/providers.tf new file mode 100644 index 0000000..53e6404 --- /dev/null +++ b/examples/gcs/providers.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + humanitec = { + source = "humanitec/humanitec" + version = "~> 0" + } + } + + required_version = ">= 1.3.0" +} + +provider "humanitec" {} diff --git a/examples/gcs/terraform.tfvars.example b/examples/gcs/terraform.tfvars.example new file mode 100644 index 0000000..e6c2341 --- /dev/null +++ b/examples/gcs/terraform.tfvars.example @@ -0,0 +1,20 @@ + +# GCP credentials +credentials = "" + +# The location of the bucket +location = "" + +# Name of the example application +name = "hum-rp-gcs-example" + +prefix = "hum-rp-gcs-ex-" + +# GCP project ID +project = "" + +# GCP Resource Pack git ref +resource_packs_gcp_rev = "refs/heads/main" + +# GCP Resource Pack git url +resource_packs_gcp_url = "https://github.com/humanitec-architecture/resource-packs-gcp.git" \ No newline at end of file diff --git a/examples/gcs/variables.tf b/examples/gcs/variables.tf new file mode 100644 index 0000000..7582714 --- /dev/null +++ b/examples/gcs/variables.tf @@ -0,0 +1,37 @@ +variable "project" { + description = "GCP project ID" + type = string +} + +variable "credentials" { + description = "GCP credentials" + type = string +} + +variable "location" { + description = "The location of the bucket" + type = string +} + +variable "resource_packs_gcp_url" { + description = "GCP Resource Pack git url" + type = string + default = "https://github.com/humanitec-architecture/resource-packs-gcp.git" +} + +variable "resource_packs_gcp_rev" { + description = "GCP Resource Pack git ref" + type = string + default = "refs/heads/main" +} + +variable "name" { + description = "Name of the example application" + type = string + default = "hum-rp-gcs-example" +} + +variable "prefix" { + type = string + default = "hum-rp-gcs-ex-" +} diff --git a/humanitec-resource-defs/gcp-service-account/workload/README.md b/humanitec-resource-defs/gcp-service-account/workload/README.md new file mode 100644 index 0000000..6d25147 --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/README.md @@ -0,0 +1,37 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| credentials | GCP credentials | `string` | n/a | yes | +| prefix | n/a | `string` | n/a | yes | +| project | GCP project ID | `string` | n/a | yes | +| resource\_packs\_gcp\_rev | GCP Resource Pack git ref | `string` | `"refs/heads/main"` | no | +| resource\_packs\_gcp\_url | GCP Resource Pack git url | `string` | `"https://github.com/humanitec-architecture/resource-packs-gcp.git"` | no | +| roles | List of roles to assign to the service account | `set(string)` | `[]` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + diff --git a/humanitec-resource-defs/gcp-service-account/workload/main.tf b/humanitec-resource-defs/gcp-service-account/workload/main.tf new file mode 100644 index 0000000..965090e --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/main.tf @@ -0,0 +1,37 @@ +resource "humanitec_resource_definition" "main" { + driver_type = "humanitec/terraform" + id = "${var.prefix}gcp-service-account-workload" + name = "${var.prefix}gcp-service-account-workload" + type = "gcp-service-account" + + driver_inputs = { + secrets_string = jsonencode({ + variables = { + credentials = var.credentials + } + }) + + values_string = jsonencode({ + source = { + path = "modules/gcp-service-account/workload" + rev = var.resource_packs_gcp_rev + url = var.resource_packs_gcp_url + } + + variables = { + project = var.project + roles = var.roles + + prefix = var.prefix + + namespace = "$${resources.k8s-namespace#k8s-namespace.outputs.namespace}" + + grants = "$${resources.workload>aws-policy.outputs.grant}" + + res_id = "$${context.res.id}" + app_id = "$${context.app.id}" + env_id = "$${context.env.id}" + } + }) + } +} diff --git a/humanitec-resource-defs/gcp-service-account/workload/outputs.tf b/humanitec-resource-defs/gcp-service-account/workload/outputs.tf new file mode 100644 index 0000000..28542ec --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/outputs.tf @@ -0,0 +1,3 @@ +output "id" { + value = humanitec_resource_definition.main.id +} diff --git a/humanitec-resource-defs/gcp-service-account/workload/providers.tf b/humanitec-resource-defs/gcp-service-account/workload/providers.tf new file mode 100644 index 0000000..86c4fc3 --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/providers.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + humanitec = { + source = "humanitec/humanitec" + version = "~> 0" + } + } + + required_version = ">= 1.3.0" +} diff --git a/humanitec-resource-defs/gcp-service-account/workload/terraform.tfvars.example b/humanitec-resource-defs/gcp-service-account/workload/terraform.tfvars.example new file mode 100644 index 0000000..47d7c12 --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/terraform.tfvars.example @@ -0,0 +1,17 @@ + +# GCP credentials +credentials = "" + +prefix = "" + +# GCP project ID +project = "" + +# GCP Resource Pack git ref +resource_packs_gcp_rev = "refs/heads/main" + +# GCP Resource Pack git url +resource_packs_gcp_url = "https://github.com/humanitec-architecture/resource-packs-gcp.git" + +# List of roles to assign to the service account +roles = [] \ No newline at end of file diff --git a/humanitec-resource-defs/gcp-service-account/workload/variables.tf b/humanitec-resource-defs/gcp-service-account/workload/variables.tf new file mode 100644 index 0000000..b6c1ba7 --- /dev/null +++ b/humanitec-resource-defs/gcp-service-account/workload/variables.tf @@ -0,0 +1,31 @@ +variable "prefix" { + type = string +} + +variable "project" { + description = "GCP project ID" + type = string +} + +variable "credentials" { + description = "GCP credentials" + type = string +} + +variable "roles" { + description = "List of roles to assign to the service account" + type = set(string) + default = [] +} + +variable "resource_packs_gcp_url" { + description = "GCP Resource Pack git url" + type = string + default = "https://github.com/humanitec-architecture/resource-packs-gcp.git" +} + +variable "resource_packs_gcp_rev" { + description = "GCP Resource Pack git ref" + type = string + default = "refs/heads/main" +} diff --git a/humanitec-resource-defs/gcs/basic/README.md b/humanitec-resource-defs/gcs/basic/README.md new file mode 100644 index 0000000..d139ec1 --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/README.md @@ -0,0 +1,39 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| credentials | GCP credentials | `string` | n/a | yes | +| location | The location of the bucket | `string` | n/a | yes | +| prefix | Name prefix | `string` | n/a | yes | +| project | GCP project ID | `string` | n/a | yes | +| force\_destroy | Whether to force destroy the bucket when deleting | `bool` | `false` | no | +| name | Resource name (can contain placeholders like ${context.app.id}) | `string` | `""` | no | +| resource\_packs\_gcp\_rev | GCP Resource Pack git ref | `string` | `"refs/heads/main"` | no | +| resource\_packs\_gcp\_url | GCP Resource Pack git url | `string` | `"https://github.com/humanitec-architecture/resource-packs-gcp.git"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + diff --git a/humanitec-resource-defs/gcs/basic/main.tf b/humanitec-resource-defs/gcs/basic/main.tf new file mode 100644 index 0000000..c88d453 --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/main.tf @@ -0,0 +1,35 @@ +resource "humanitec_resource_definition" "main" { + driver_type = "humanitec/terraform" + id = "${var.prefix}gcs-basic" + name = "${var.prefix}gcs-basic" + type = "gcs" + + driver_inputs = { + secrets_string = jsonencode({ + variables = { + credentials = var.credentials + } + }) + + values_string = jsonencode({ + source = { + path = "modules/gcs/basic" + rev = var.resource_packs_gcp_rev + url = var.resource_packs_gcp_url + } + + variables = { + prefix = var.prefix + name = var.name + + res_id = "$${context.res.id}" + app_id = "$${context.app.id}" + env_id = "$${context.env.id}" + + project = var.project + force_destroy = var.force_destroy + location = var.location + } + }) + } +} diff --git a/humanitec-resource-defs/gcs/basic/outputs.tf b/humanitec-resource-defs/gcs/basic/outputs.tf new file mode 100644 index 0000000..28542ec --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/outputs.tf @@ -0,0 +1,3 @@ +output "id" { + value = humanitec_resource_definition.main.id +} diff --git a/humanitec-resource-defs/gcs/basic/providers.tf b/humanitec-resource-defs/gcs/basic/providers.tf new file mode 100644 index 0000000..86c4fc3 --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/providers.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + humanitec = { + source = "humanitec/humanitec" + version = "~> 0" + } + } + + required_version = ">= 1.3.0" +} diff --git a/humanitec-resource-defs/gcs/basic/terraform.tfvars.example b/humanitec-resource-defs/gcs/basic/terraform.tfvars.example new file mode 100644 index 0000000..54ca594 --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/terraform.tfvars.example @@ -0,0 +1,24 @@ + +# GCP credentials +credentials = "" + +# Whether to force destroy the bucket when deleting +force_destroy = false + +# The location of the bucket +location = "" + +# Resource name (can contain placeholders like ${context.app.id}) +name = "" + +# Name prefix +prefix = "" + +# GCP project ID +project = "" + +# GCP Resource Pack git ref +resource_packs_gcp_rev = "refs/heads/main" + +# GCP Resource Pack git url +resource_packs_gcp_url = "https://github.com/humanitec-architecture/resource-packs-gcp.git" \ No newline at end of file diff --git a/humanitec-resource-defs/gcs/basic/variables.tf b/humanitec-resource-defs/gcs/basic/variables.tf new file mode 100644 index 0000000..105ddda --- /dev/null +++ b/humanitec-resource-defs/gcs/basic/variables.tf @@ -0,0 +1,43 @@ +variable "resource_packs_gcp_url" { + description = "GCP Resource Pack git url" + type = string + default = "https://github.com/humanitec-architecture/resource-packs-gcp.git" +} + +variable "resource_packs_gcp_rev" { + description = "GCP Resource Pack git ref" + type = string + default = "refs/heads/main" +} + +variable "project" { + description = "GCP project ID" + type = string +} + +variable "credentials" { + description = "GCP credentials" + type = string +} + +variable "force_destroy" { + description = "Whether to force destroy the bucket when deleting" + type = bool + default = false +} + +variable "location" { + description = "The location of the bucket" + type = string +} + +variable "prefix" { + type = string + description = "Name prefix" +} + +variable "name" { + type = string + description = "Resource name (can contain placeholders like $${context.app.id})" + default = "" +} diff --git a/humanitec-resource-defs/gcs/passthrough/README.md b/humanitec-resource-defs/gcs/passthrough/README.md new file mode 100644 index 0000000..9271c8a --- /dev/null +++ b/humanitec-resource-defs/gcs/passthrough/README.md @@ -0,0 +1,34 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| gcs\_resource\_class | n/a | `string` | n/a | yes | +| policy\_resource\_class | n/a | `string` | n/a | yes | +| prefix | n/a | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + \ No newline at end of file diff --git a/humanitec-resource-defs/gcs/passthrough/main.tf b/humanitec-resource-defs/gcs/passthrough/main.tf new file mode 100644 index 0000000..0872aa2 --- /dev/null +++ b/humanitec-resource-defs/gcs/passthrough/main.tf @@ -0,0 +1,23 @@ +resource "humanitec_resource_definition" "main" { + driver_type = "humanitec/template" + id = "${var.prefix}gcs-${var.gcs_resource_class}-${var.policy_resource_class}" + name = "${var.prefix}gcs-${var.gcs_resource_class}-${var.policy_resource_class}" + type = "gcs" + + driver_inputs = { + values_string = jsonencode({ + templates = { + outputs = < +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| gcs\_resource\_class | The class of the GCS resource | `string` | n/a | yes | +| name | Resource definition name | `string` | n/a | yes | +| prefix | n/a | `string` | n/a | yes | +| role | The role to bind to the GCS resource | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + diff --git a/humanitec-resource-defs/iam-role-binding/gcs/main.tf b/humanitec-resource-defs/iam-role-binding/gcs/main.tf new file mode 100644 index 0000000..aa5f3ab --- /dev/null +++ b/humanitec-resource-defs/iam-role-binding/gcs/main.tf @@ -0,0 +1,23 @@ +resource "humanitec_resource_definition" "main" { + driver_type = "humanitec/template" + id = "${var.prefix}iam-role-biding-gcs-${var.name}" + name = "${var.prefix}iam-role-biding-gcs-${var.name}" + + # TODO Switch the GCP type once available + type = "aws-policy" + + driver_inputs = { + values_string = jsonencode({ + templates = { + outputs = < +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| prefix | n/a | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + \ No newline at end of file diff --git a/humanitec-resource-defs/k8s/service-account/main.tf b/humanitec-resource-defs/k8s/service-account/main.tf new file mode 100644 index 0000000..450fe92 --- /dev/null +++ b/humanitec-resource-defs/k8s/service-account/main.tf @@ -0,0 +1,39 @@ +resource "humanitec_resource_definition" "main" { + id = "${var.prefix}k8s-service-account" + name = "${var.prefix}k8s-service-account" + type = "k8s-service-account" + + driver_type = "humanitec/template" + driver_inputs = { + secrets_string = jsonencode({ + templates = { + # outputs = "" + } + }) + + values_string = jsonencode({ + templates = { + # cookie = "" + init = "" + manifests = < +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| humanitec | ~> 0 | + +## Providers + +| Name | Version | +|------|---------| +| humanitec | ~> 0 | + +## Resources + +| Name | Type | +|------|------| +| [humanitec_resource_definition.main](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| prefix | n/a | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| id | n/a | + \ No newline at end of file diff --git a/humanitec-resource-defs/workload/service-account/main.tf b/humanitec-resource-defs/workload/service-account/main.tf new file mode 100644 index 0000000..ea794e1 --- /dev/null +++ b/humanitec-resource-defs/workload/service-account/main.tf @@ -0,0 +1,21 @@ +resource "humanitec_resource_definition" "main" { + id = "${var.prefix}workload" + name = "${var.prefix}workload" + type = "workload" + + driver_type = "humanitec/template" + driver_inputs = { + values_string = jsonencode({ + templates = { + # cookie = "" + init = "" + outputs = < +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| google | ~> 5.1 | + +## Providers + +| Name | Version | +|------|---------| +| google | ~> 5.1 | + +## Resources + +| Name | Type | +|------|------| +| [google_project_iam_member.role](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/project_iam_member) | resource | +| [google_service_account.main](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account) | resource | +| [google_service_account_iam_member.workload_identity_k8s_service_account](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_account_iam_member) | resource | +| [google_storage_bucket_iam_member.main](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket_iam_member) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| app\_id | n/a | `string` | n/a | yes | +| bindings | List of additional bindings to grant to the service account | `set(string)` | n/a | yes | +| credentials | GCP credentials | `string` | n/a | yes | +| env\_id | n/a | `string` | n/a | yes | +| namespace | k8s namespace | `string` | n/a | yes | +| prefix | n/a | `string` | n/a | yes | +| project | GCP project ID | `string` | n/a | yes | +| res\_id | n/a | `string` | n/a | yes | +| roles | List of project-level roles to grant to the service account | `set(string)` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| email | n/a | +| k8s\_service\_account\_name | n/a | + \ No newline at end of file diff --git a/modules/gcp-service-account/workload/bindings.tf b/modules/gcp-service-account/workload/bindings.tf new file mode 100644 index 0000000..8ca5a89 --- /dev/null +++ b/modules/gcp-service-account/workload/bindings.tf @@ -0,0 +1,14 @@ +locals { + parsed_bindings = [for g in var.bindings : jsondecode(g)] +} + +resource "google_storage_bucket_iam_member" "main" { + for_each = { + for g in local.parsed_bindings : + join("/", [g["bucket"], g["role"]]) => g if g["type"] == "storage_bucket" + } + + bucket = each.value["bucket"] + role = each.value["role"] + member = "serviceAccount:${google_service_account.main.email}" +} diff --git a/modules/gcp-service-account/workload/main.tf b/modules/gcp-service-account/workload/main.tf new file mode 100644 index 0000000..64600fb --- /dev/null +++ b/modules/gcp-service-account/workload/main.tf @@ -0,0 +1,22 @@ +locals { + k8s_service_account_name = "${var.app_id}-${var.env_id}-${trimprefix(var.res_id, "modules.")}" +} + +resource "google_service_account" "main" { + display_name = "${var.prefix}workload service account" + account_id = "${var.prefix}workload" +} + +resource "google_project_iam_member" "role" { + for_each = var.roles + + project = var.project + role = each.key + member = "serviceAccount:${google_service_account.main.email}" +} + +resource "google_service_account_iam_member" "workload_identity_k8s_service_account" { + service_account_id = google_service_account.main.name + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.project}.svc.id.goog[${var.namespace}/${local.k8s_service_account_name}]" +} diff --git a/modules/gcp-service-account/workload/outputs.tf b/modules/gcp-service-account/workload/outputs.tf new file mode 100644 index 0000000..25c46d0 --- /dev/null +++ b/modules/gcp-service-account/workload/outputs.tf @@ -0,0 +1,7 @@ +output "email" { + value = google_service_account.main.email +} + +output "k8s_service_account_name" { + value = local.k8s_service_account_name +} diff --git a/modules/gcp-service-account/workload/providers.tf b/modules/gcp-service-account/workload/providers.tf new file mode 100644 index 0000000..81d5bf8 --- /dev/null +++ b/modules/gcp-service-account/workload/providers.tf @@ -0,0 +1,23 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.1" + } + } + + required_version = ">= 1.3.0" +} + +provider "google" { + project = var.project + credentials = var.credentials + + # TODO + default_labels = { + "managed-by" = "humanitec" + "hum-app-id" = var.app_id + "hum-env-id" = var.env_id + # "hum-res-id" = var.res_id + } +} diff --git a/modules/gcp-service-account/workload/terraform.tfvars.example b/modules/gcp-service-account/workload/terraform.tfvars.example new file mode 100644 index 0000000..7e7bef0 --- /dev/null +++ b/modules/gcp-service-account/workload/terraform.tfvars.example @@ -0,0 +1,22 @@ +app_id = "" + +# List of additional bindings to grant to the service account +bindings = "" + +# GCP credentials +credentials = "" + +env_id = "" + +# k8s namespace +namespace = "" + +prefix = "" + +# GCP project ID +project = "" + +res_id = "" + +# List of project-level roles to grant to the service account +roles = "" \ No newline at end of file diff --git a/modules/gcp-service-account/workload/variables.tf b/modules/gcp-service-account/workload/variables.tf new file mode 100644 index 0000000..5e0806d --- /dev/null +++ b/modules/gcp-service-account/workload/variables.tf @@ -0,0 +1,40 @@ +variable "prefix" { + type = string +} + +variable "app_id" { + type = string +} + +variable "env_id" { + type = string +} + +variable "res_id" { + type = string +} + +variable "project" { + description = "GCP project ID" + type = string +} + +variable "credentials" { + description = "GCP credentials" + type = string +} + +variable "namespace" { + description = "k8s namespace" + type = string +} + +variable "roles" { + description = "List of project-level roles to grant to the service account" + type = set(string) +} + +variable "bindings" { + description = "List of additional bindings to grant to the service account" + type = set(string) +} diff --git a/modules/gcs/basic/README.md b/modules/gcs/basic/README.md new file mode 100644 index 0000000..fc371ac --- /dev/null +++ b/modules/gcs/basic/README.md @@ -0,0 +1,40 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 1.3.0 | +| google | ~> 5.1 | + +## Providers + +| Name | Version | +|------|---------| +| google | ~> 5.1 | + +## Resources + +| Name | Type | +|------|------| +| [google_storage_bucket.main](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| app\_id | n/a | `string` | n/a | yes | +| credentials | GCP credentials | `string` | n/a | yes | +| env\_id | n/a | `string` | n/a | yes | +| location | The location of the bucket | `string` | n/a | yes | +| prefix | n/a | `string` | n/a | yes | +| project | GCP project ID | `string` | n/a | yes | +| res\_id | n/a | `string` | n/a | yes | +| force\_destroy | Whether to force destroy the bucket when deleting | `bool` | `false` | no | +| name | n/a | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| name | n/a | + \ No newline at end of file diff --git a/modules/gcs/basic/main.tf b/modules/gcs/basic/main.tf new file mode 100644 index 0000000..2f95e96 --- /dev/null +++ b/modules/gcs/basic/main.tf @@ -0,0 +1,16 @@ +locals { + # Name restrictions https://cloud.google.com/storage/docs/buckets#naming + default_name = substr("${var.prefix}${var.app_id}-${var.env_id}-${replace(var.res_id, ".", "-")}", 0, 63) +} + +resource "google_storage_bucket" "main" { + name = coalesce(var.name, local.default_name) + location = var.location + force_destroy = var.force_destroy + + uniform_bucket_level_access = true + + versioning { + enabled = true + } +} diff --git a/modules/gcs/basic/outputs.tf b/modules/gcs/basic/outputs.tf new file mode 100644 index 0000000..fa33156 --- /dev/null +++ b/modules/gcs/basic/outputs.tf @@ -0,0 +1,3 @@ +output "name" { + value = google_storage_bucket.main.name +} diff --git a/modules/gcs/basic/providers.tf b/modules/gcs/basic/providers.tf new file mode 100644 index 0000000..fe717ca --- /dev/null +++ b/modules/gcs/basic/providers.tf @@ -0,0 +1,22 @@ +terraform { + required_providers { + google = { + source = "hashicorp/google" + version = "~> 5.1" + } + } + + required_version = ">= 1.3.0" +} + +provider "google" { + project = var.project + credentials = var.credentials + + default_labels = { + "humanitec" = "true" + "hum-app-id" = var.app_id + "hum-env-id" = var.env_id + "hum-res-id" = replace(var.res_id, ".", "-") + } +} diff --git a/modules/gcs/basic/terraform.tfvars.example b/modules/gcs/basic/terraform.tfvars.example new file mode 100644 index 0000000..6953b42 --- /dev/null +++ b/modules/gcs/basic/terraform.tfvars.example @@ -0,0 +1,20 @@ +app_id = "" + +# GCP credentials +credentials = "" + +env_id = "" + +# Whether to force destroy the bucket when deleting +force_destroy = false + +# The location of the bucket +location = "" + +name = "" +prefix = "" + +# GCP project ID +project = "" + +res_id = "" \ No newline at end of file diff --git a/modules/gcs/basic/variables.tf b/modules/gcs/basic/variables.tf new file mode 100644 index 0000000..4e6ce0b --- /dev/null +++ b/modules/gcs/basic/variables.tf @@ -0,0 +1,41 @@ +variable "prefix" { + type = string +} + +variable "name" { + type = string + default = "" +} + +variable "app_id" { + type = string +} + +variable "env_id" { + type = string +} + +variable "res_id" { + type = string +} + +variable "project" { + description = "GCP project ID" + type = string +} + +variable "credentials" { + description = "GCP credentials" + type = string +} + +variable "force_destroy" { + description = "Whether to force destroy the bucket when deleting" + type = bool + default = false +} + +variable "location" { + description = "The location of the bucket" + type = string +}