Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: shared cloudsql instances & cloudsql iam authentication #14

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading