Skip to content

Commit

Permalink
Merge pull request #14 from johanneswuerbach/sqliam
Browse files Browse the repository at this point in the history
feat: shared cloudsql instances & cloudsql iam authentication
  • Loading branch information
johanneswuerbach authored Apr 8, 2024
2 parents 297dacb + 3e500f1 commit bdf834e
Show file tree
Hide file tree
Showing 50 changed files with 1,274 additions and 152 deletions.
23 changes: 17 additions & 6 deletions examples/mysql/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Example: mysql resource based on GCP CloudSQL

## Configuration

This example configures a [mysql](https://developer.humanitec.com/platform-orchestrator/reference/resource-types/#mysql) Resource Definition using GCP CloudSQL. A workload using the `mysql` resource to create database instance looks like:

```yaml
Expand All @@ -19,27 +20,35 @@ resources:
type: mysql
```
This example uses username and password authentication, checkout [../postgres/README.md](postgres) for an example using CloudSQL IAM Authentication.
## Infrastructure setup
```mermaid
graph TD;
subgraph VPC
database["MySQl GCP CloudSQL"]
subgraph server["MySQL CloudSQL Database Instance"]
database["CloudSQL Database"]
user["CloudSQL User"]
end
subgraph GKE Cluster
pod[workload pod]
pod -- CloudSQL User with password --> database
end
database --> pod
end
```

## Orchestrator setup

```mermaid
graph LR;
workload_1 --> db_1["db_1, resource_type: mysql"]
workload_2 --> db_2["db_2, resource_type: mysql"]
workload_2 --> shared.db_1["shared.db_1, resource_type: mysql"]
workload_3 --> shared.db_1["shared.db_1, resource_type: mysql"]
workload_1 --> db_1["db_1, resource_type: mysql"]
workload_2 --> db_2["db_2, resource_type: mysql"]
workload_2 --> shared.db_1["shared.db_1, resource_type: mysql"]
workload_3 --> shared.db_1["shared.db_1, resource_type: mysql"]
db_1 --> server["main-mysql, resource_type: mysql-instance"]
db_2 --> server
shared.db_1 --> server
```

<!-- BEGIN_TF_DOCS -->
Expand All @@ -63,6 +72,7 @@ graph LR;
| Name | Source | Version |
|------|--------|---------|
| mysql | ../../humanitec-resource-defs/mysql/basic | n/a |
| mysql\_instance | ../../humanitec-resource-defs/mysql-instance/basic | n/a |

## Resources

Expand All @@ -77,6 +87,7 @@ graph LR;
| [humanitec_application.example](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/application) | resource |
| [humanitec_resource_account.humanitec_provisioner](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_account) | resource |
| [humanitec_resource_definition_criteria.mysql](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
| [humanitec_resource_definition_criteria.mysql_instance](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
| [google_compute_network.network](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/compute_network) | data source |

## Inputs
Expand Down
38 changes: 36 additions & 2 deletions examples/mysql/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ resource "humanitec_application" "example" {
name = var.name
}

# MySQL instance

locals {
# Define the shared mysql-instance resource id and class
mysql_instance_res_id = "main-mysql"
mysql_instance_class = "default"
}

data "google_compute_network" "network" {
name = var.private_network
}
Expand All @@ -52,6 +60,10 @@ resource "google_compute_global_address" "private_ip_address" {
network = data.google_compute_network.network.id
}

# In case of getting "Cannot modify allocated ranges in CreateConnection. Please use UpdateConnection.",
# temporarily set `reserved_peering_ranges = []` run apply, reset afterwards and apply again.
#
# This is required due to https://github.com/hashicorp/terraform-provider-google/issues/3294
resource "google_service_networking_connection" "private_vpc_connection" {
network = data.google_compute_network.network.id
service = "servicenetworking.googleapis.com"
Expand All @@ -60,8 +72,8 @@ resource "google_service_networking_connection" "private_vpc_connection" {
depends_on = [google_project_service.servicenetworking]
}

module "mysql" {
source = "../../humanitec-resource-defs/mysql/basic"
module "mysql_instance" {
source = "../../humanitec-resource-defs/mysql-instance/basic"

prefix = var.prefix
resource_packs_gcp_rev = var.resource_packs_gcp_rev
Expand All @@ -78,6 +90,28 @@ module "mysql" {
depends_on = [google_service_networking_connection.private_vpc_connection]
}

resource "humanitec_resource_definition_criteria" "mysql_instance" {
resource_definition_id = module.mysql_instance.id
app_id = humanitec_application.example.id
class = local.mysql_instance_class
res_id = local.mysql_instance_res_id
force_delete = true
}

module "mysql" {
source = "../../humanitec-resource-defs/mysql/basic"

prefix = var.prefix
resource_packs_gcp_rev = var.resource_packs_gcp_rev
resource_packs_gcp_url = var.resource_packs_gcp_url
append_logs_to_error = true
driver_account = humanitec_resource_account.humanitec_provisioner.id
project = var.project
region = var.region

instance_resource = "mysql-instance.${local.mysql_instance_class}#${local.mysql_instance_res_id}"
}

resource "humanitec_resource_definition_criteria" "mysql" {
resource_definition_id = module.mysql.id
app_id = humanitec_application.example.id
Expand Down
56 changes: 45 additions & 11 deletions examples/postgres/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Example: postgres resource based on GCP CloudSQL

## Configuration

This example configures a [postgres](https://developer.humanitec.com/platform-orchestrator/reference/resource-types/#postgres) Resource Definition using GCP CloudSQL. A workload using the `postgres` resource to create database instance looks like:

```yaml
Expand All @@ -19,27 +20,50 @@ resources:
type: postgres
```
This example uses [CloudSQL IAM Authentication](https://cloud.google.com/sql/docs/postgres/iam-authentication), checkout [../mysql/README.md](mysql) for an example using username and password authentication.
CloudSQL IAM Authentication is enabled by automatically injecting the [Cloud SQL Auth Proxy](https://cloud.google.com/sql/docs/postgres/sql-proxy) as sidecar into each workload that is using a `postgres` resource.

## Infrastructure setup

```mermaid
graph TD;
subgraph VPC
database["Postgres GCP CloudSQL"]
graph TD
subgraph GCP IAM
gcp_db_serviceaccount[GCP Service Account - db user]
gcp_k8s_serviceaccount[GCP Service Account - k8s user]
end
subgraph VPC
subgraph server["PostgreSQL CloudSQL Database Instance"]
database["CloudSQL Database"]
user["CloudSQL User"]
end
subgraph GKE Cluster
pod[workload pod]
subgraph pod[workload pod]
workload-container --> cloud-sql-proxy-container
cloud-sql-proxy-container -- CloudSQL User with iam authentication using GCP Service Account [db user] --> database
end
service[K8s Service Account] --> gcp_k8s_serviceaccount
end
database --> pod
end
gcp_k8s_serviceaccount -- workload identity user --> gcp_db_serviceaccount
end
gcp_db_serviceaccount --> user
gcp_db_serviceaccount -- cloudsql.client & instanceUser --> server
```

## Orchestrator setup

```mermaid
graph LR;
workload_1 --> db_1["db_1, resource_type: mysql"]
workload_2 --> db_2["db_2, resource_type: mysql"]
workload_2 --> shared.db_1["shared.db_1, resource_type: mysql"]
workload_3 --> shared.db_1["shared.db_1, resource_type: mysql"]
workload_1 --> db_1["db_1, resource_type: postgres"]
workload_2 --> db_2["db_2, resource_type: postgres"]
workload_2 --> shared.db_1["shared.db_1, resource_type: postgres"]
workload_3 --> shared.db_1["shared.db_1, resource_type: postgres"]
db_1 --> server["main-postgres, resource_type: postgres-instance"]
db_2 --> server
shared.db_1 --> server
```

<!-- BEGIN_TF_DOCS -->
Expand All @@ -62,7 +86,12 @@ graph LR;

| Name | Source | Version |
|------|--------|---------|
| postgres | ../../humanitec-resource-defs/postgres/basic | n/a |
| gcp\_service\_account\_workload | ../../humanitec-resource-defs/gcp-service-account/workload | n/a |
| iam\_role\_binding\_service\_account\_workload\_identity | ../../humanitec-resource-defs/gcp-iam-policy-binding/basic | n/a |
| k8s\_service\_account | ../../humanitec-resource-defs/k8s/service-account | n/a |
| postgres | ../../humanitec-resource-defs/postgres/workload-identity | n/a |
| postgres\_instance | ../../humanitec-resource-defs/postgres-instance/basic | n/a |
| workload | ../../humanitec-resource-defs/workload/service-account | n/a |

## Resources

Expand All @@ -76,7 +105,12 @@ graph LR;
| [google_service_networking_connection.private_vpc_connection](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/service_networking_connection) | resource |
| [humanitec_application.example](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/application) | resource |
| [humanitec_resource_account.humanitec_provisioner](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_account) | 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.iam_role_binding_service_account_workload_identity](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.postgres](https://registry.terraform.io/providers/humanitec/humanitec/latest/docs/resources/resource_definition_criteria) | resource |
| [humanitec_resource_definition_criteria.postgres_instance](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 |
| [google_compute_network.network](https://registry.terraform.io/providers/hashicorp/google/latest/docs/data-sources/compute_network) | data source |

## Inputs
Expand Down
115 changes: 111 additions & 4 deletions examples/postgres/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ resource "humanitec_application" "example" {
name = var.name
}

# Postgres instance

locals {
# Define the shared postgres-instance resource id and class
postgres_instance_res_id = "main-postgres"
postgres_instance_class = "default"

# Individual postgres resource class
postgres_basic_class = "default"

# Service account workload identity policy class
postgres_service_account_workload_identity_policy_class = "postgres-service-account-workload-identity"
}


data "google_compute_network" "network" {
name = var.private_network
}
Expand All @@ -52,8 +67,10 @@ resource "google_compute_global_address" "private_ip_address" {
network = data.google_compute_network.network.id
}

# There is a bug
# walkaround `gcloud services vpc-peerings update --network=htc-ref-arch-vpc --ranges=hum-rp-mysql-ex-private-ip-address --service=servicenetworking.googleapis.com --force`
# In case of getting "Cannot modify allocated ranges in CreateConnection. Please use UpdateConnection.",
# temporarily set `reserved_peering_ranges = []` run apply, reset afterwards and apply again.
#
# This is required due to https://github.com/hashicorp/terraform-provider-google/issues/3294
resource "google_service_networking_connection" "private_vpc_connection" {
network = data.google_compute_network.network.id
service = "servicenetworking.googleapis.com"
Expand All @@ -62,8 +79,8 @@ resource "google_service_networking_connection" "private_vpc_connection" {
depends_on = [google_project_service.servicenetworking]
}

module "postgres" {
source = "../../humanitec-resource-defs/postgres/basic"
module "postgres_instance" {
source = "../../humanitec-resource-defs/postgres-instance/basic"

prefix = var.prefix
resource_packs_gcp_rev = var.resource_packs_gcp_rev
Expand All @@ -80,8 +97,98 @@ module "postgres" {
depends_on = [google_service_networking_connection.private_vpc_connection]
}

resource "humanitec_resource_definition_criteria" "postgres_instance" {
resource_definition_id = module.postgres_instance.id
app_id = humanitec_application.example.id
class = local.postgres_instance_class
res_id = local.postgres_instance_res_id
force_delete = true
}

module "postgres" {
source = "../../humanitec-resource-defs/postgres/workload-identity"

prefix = var.prefix
resource_packs_gcp_rev = var.resource_packs_gcp_rev
resource_packs_gcp_url = var.resource_packs_gcp_url
append_logs_to_error = true
driver_account = humanitec_resource_account.humanitec_provisioner.id
project = var.project
region = var.region

instance_resource = "postgres-instance.${local.postgres_instance_class}#${local.postgres_instance_res_id}"
policy_resource_class = local.postgres_service_account_workload_identity_policy_class
}

resource "humanitec_resource_definition_criteria" "postgres" {
resource_definition_id = module.postgres.id
app_id = humanitec_application.example.id
class = local.postgres_basic_class
force_delete = true
}

# IAM role binding to be able to assume to database service account with workload identity
module "iam_role_binding_service_account_workload_identity" {
source = "../../humanitec-resource-defs/gcp-iam-policy-binding/basic"

prefix = var.prefix
name = "gcp-iam-policy-binding-sa-workload-identity"

type = "service_account"
scope_key = "service_account_id"
scope_value = "$${resources['postgres.${local.postgres_basic_class}'].outputs.service_account_id}"
role = "roles/iam.workloadIdentityUser"
}

resource "humanitec_resource_definition_criteria" "iam_role_binding_service_account_workload_identity" {
resource_definition_id = module.iam_role_binding_service_account_workload_identity.id
app_id = humanitec_application.example.id
class = local.postgres_service_account_workload_identity_policy_class
force_delete = true
}

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

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
append_logs_to_error = true
driver_account = humanitec_resource_account.humanitec_provisioner.id

project = var.project
prefix = var.prefix

name = "hrp-pg-$${context.res.id}"
}

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

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

0 comments on commit bdf834e

Please sign in to comment.