Resource Packs

Cloud

Example

Flavor

Feature

Gcs

Example: gcs resource based on Google Cloud Storage

Configuration

This example configures a 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:

containers:
  app:
    ...
    variables:
      BUCKET_NAME: ${resources.gcs.name}
resources:
  ...
  gcs:
    type: gcs
    class: basic-admin

Infrastructure setup

The workload service account will be automatically assigned to the necessary role with the selected policy.

graph TD;
  gcs["Google Cloud Storage"]
  subgraph GKE Cluster
    pod[workload pod]
    service[k8s service account]
  end
  service -- bind role on --> gcs
  service --> pod
  gcs --> pod

Orchestrator setup

The Resource Graph is using delegator resources to expose shared resources with different access policies.

graph LR;
  workload_1 --> delegator_1["delegator_1, resource_type: gcs", class: basic-read-only] --> shared.gcs_1["shared.gcs_1, resource_type: gcs"]
  workload_2 --> delegator_2["delegator_2, resource_type: gcs, class: basic-admin"] --> shared.gcs_1
  workload_2 --> shared.delegator_1["shared.delegator_1, resource_type: gcs, class: basic-read-only"]
  workload_3 --> shared.delegator_1 --> shared.gcs_2["shared.gcs_2, resource_type: gcs"]

Terraform docs

Requirements

Name Version
terraform >= 1.3.0
google ~> 5.17
humanitec ~> 1.0

Providers

Name Version
google ~> 5.17
humanitec ~> 1.0

Modules

Name Source Version
gcs_basic ../../humanitec-resource-defs/gcs/basic n/a
gcs_basic_admin ../../humanitec-resource-defs/gcs/delegator n/a
gcs_basic_read_only ../../humanitec-resource-defs/gcs/delegator n/a
iam_role_binding_gcs_admin ../../humanitec-resource-defs/gcp-iam-policy-binding/basic n/a
iam_role_binding_gcs_read_only ../../humanitec-resource-defs/gcp-iam-policy-binding/basic n/a
k8s_service_account_workload ../../humanitec-resource-defs/k8s-service-account/workload n/a
workload ../../humanitec-resource-defs/workload/service-account n/a

Resources

Name Type
google_project_iam_member.humanitec_provisioner resource
google_service_account.humanitec_provisioner resource
google_service_account_key.humanitec_provisioner resource
humanitec_application.example resource
humanitec_resource_account.humanitec_provisioner resource
humanitec_resource_definition_criteria.gcs_basic resource
humanitec_resource_definition_criteria.gcs_basic_admin resource
humanitec_resource_definition_criteria.gcs_basic_read_only resource
humanitec_resource_definition_criteria.iam_role_binding_gcs_admin resource
humanitec_resource_definition_criteria.iam_role_binding_gcs_read_only resource
humanitec_resource_definition_criteria.k8s_service_account_workload resource
humanitec_resource_definition_criteria.workload resource

Inputs

Name Description Type Default Required
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 Prefix of the created resources 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

main.tf ( view on GitHub ) :

# GCP service account used by Humanitec to provision resources

resource "google_service_account" "humanitec_provisioner" {
  account_id  = var.name
  description = "Account used by Humanitec to provision resources"
}

resource "google_project_iam_member" "humanitec_provisioner" {
  project = var.project
  role    = "roles/owner"
  member  = "serviceAccount:${google_service_account.humanitec_provisioner.email}"
}

resource "google_service_account_key" "humanitec_provisioner" {
  service_account_id = google_service_account.humanitec_provisioner.name
}

resource "humanitec_resource_account" "humanitec_provisioner" {
  id   = var.name
  name = var.name
  type = "gcp"

  credentials = base64decode(google_service_account_key.humanitec_provisioner.private_key)

  depends_on = [
    # Otherwise the account looses permissions before the resources are deleted
    google_project_iam_member.humanitec_provisioner
  ]
}

# Example application and resource definition criteria

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 = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/gcs/basic"

  resource_packs_gcp_url = var.resource_packs_gcp_url
  resource_packs_gcp_rev = var.resource_packs_gcp_rev
  append_logs_to_error   = true
  driver_account         = humanitec_resource_account.humanitec_provisioner.id

  project       = var.project
  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
  force_delete           = true
}

# Add different access policy to gcs basic bucket

# Admin

## Policy

module "iam_role_binding_gcs_admin" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/gcp-iam-policy-binding/basic"

  prefix = var.prefix
  name   = "gcp-iam-policy-binding-gcs-basic-admin"

  type        = "storage_bucket"
  scope_key   = "bucket"
  scope_value = "$${resources['gcs.${local.gcs_basic_class}'].outputs.name}"
  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
  force_delete           = true
}

## Exposed delegator resource definition
module "gcs_basic_admin" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/gcs/delegator"

  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
  force_delete           = true
}

# Read-only

## Policy

module "iam_role_binding_gcs_read_only" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/gcp-iam-policy-binding/basic"

  prefix = var.prefix
  name   = "gcs-basic-read-only"

  type        = "storage_bucket"
  scope_key   = "bucket"
  scope_value = "$${resources['gcs.${local.gcs_basic_class}'].outputs.name}"
  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
  force_delete           = true
}

## Exposed delegator resource definition
module "gcs_basic_read_only" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/gcs/delegator"

  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
  force_delete           = true
}

# Required resources for workload identity

module "k8s_service_account_workload" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//humanitec-resource-defs/k8s-service-account/workload"

  resource_packs_gcp_url = var.resource_packs_gcp_url
  resource_packs_gcp_rev = var.resource_packs_gcp_rev
  append_logs_to_error   = true
  driver_account         = humanitec_resource_account.humanitec_provisioner.id

  project = var.project
  prefix  = var.prefix
}

resource "humanitec_resource_definition_criteria" "k8s_service_account_workload" {
  resource_definition_id = module.k8s_service_account_workload.id
  app_id                 = humanitec_application.example.id
  force_delete           = true
}

module "workload" {
  source = "github.com/humanitec-architecture/resource-packs-gcp?ref=v2024-06-14//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
  force_delete           = true
}


providers.tf ( view on GitHub ) :

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.17"
    }
    humanitec = {
      source  = "humanitec/humanitec"
      version = "~> 1.0"
    }
  }

  required_version = ">= 1.3.0"
}

provider "humanitec" {}

provider "google" {
  project = var.project

  default_labels = {
    "managed_by" = "terraform"
    "source"     = "github.com/humanitec-architecture/resource-pack-gcp"
  }
}


terraform.tfvars.example ( view on GitHub ) :


# The location of the bucket
location = ""

# Name of the example application
name = "hum-rp-gcs-example"

# Prefix of the created resources
prefix = "hum-rp-gcs-ex-"

# GCP project ID
project = ""

# GCP Resource Pack git ref
resource_packs_gcp_rev = "refs/tags/v2024-06-14"

# GCP Resource Pack git url
resource_packs_gcp_url = "https://github.com/humanitec-architecture/resource-packs-gcp.git"

variables.tf ( view on GitHub ) :

variable "project" {
  description = "GCP project ID"
  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/tags/v2024-06-14"
}

variable "name" {
  description = "Name of the example application"
  type        = string
  default     = "hum-rp-gcs-example"
}

variable "prefix" {
  description = "Prefix of the created resources"
  type        = string
  default     = "hum-rp-gcs-ex-"
}

Top