Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
erdrix committed Sep 24, 2022
1 parent 07078cb commit 41536ee
Show file tree
Hide file tree
Showing 6 changed files with 445 additions and 0 deletions.
Empty file added CHANGELOG.md
Empty file.
72 changes: 72 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<!-- BEGIN_TF_DOCS -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >=0.15 |
| <a name="requirement_google"></a> [google](#requirement\_google) | >= 3.89.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.1.0 |
| <a name="requirement_vault"></a> [vault](#requirement\_vault) | >= 2.17.0 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_google"></a> [google](#provider\_google) | >= 3.89.0 |
| <a name="provider_google-beta"></a> [google-beta](#provider\_google-beta) | n/a |
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.1.0 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [google-beta_google_secret_manager_secret.registry_sql_client_cert](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_secret_manager_secret) | resource |
| [google-beta_google_secret_manager_secret.registry_sql_user_password](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_secret_manager_secret) | resource |
| [google-beta_google_secret_manager_secret_version.registry_sql_client_cert](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_secret_manager_secret_version) | resource |
| [google-beta_google_secret_manager_secret_version.secret-version-basic](https://registry.terraform.io/providers/hashicorp/google-beta/latest/docs/resources/google_secret_manager_secret_version) | resource |
| [google_sql_database.cloudsql_database](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database) | resource |
| [google_sql_database_instance.cloudsql_instance](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_database_instance) | resource |
| [google_sql_ssl_cert.client_cert](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_ssl_cert) | resource |
| [google_sql_user.cloudsql_user](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/sql_user) | resource |
| [random_password.cloudsql_user_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_authorized_cidrs"></a> [authorized\_cidrs](#input\_authorized\_cidrs) | Authorized networks CIDRs to connect to Cloud SQL instance. | `map(string)` | `{}` | no |
| <a name="input_backup_configuration"></a> [backup\_configuration](#input\_backup\_configuration) | The backup\_configuration subblock for the database setings | <pre>list(object({<br> enabled = bool<br> start_time = string<br> location = string<br> retained_backups = number<br> }))</pre> | `[]` | no |
| <a name="input_cert_common_name"></a> [cert\_common\_name](#input\_cert\_common\_name) | Certificate Common Name. | `string` | n/a | yes |
| <a name="input_database_version"></a> [database\_version](#input\_database\_version) | Database type and version. Supported values = {MYSQL\_5\_6, MYSQL\_5\_7, MYSQL\_8\_0, POSTGRES\_9\_6,POSTGRES\_10, POSTGRES\_11, POSTGRES\_12, POSTGRES\_13, ...}. See {Instance settings documentation} | `string` | n/a | yes |
| <a name="input_db_name"></a> [db\_name](#input\_db\_name) | Full name of the SQL database. | `string` | n/a | yes |
| <a name="input_deletion_protection"></a> [deletion\_protection](#input\_deletion\_protection) | If set to true, you protect an instance from being deleted. | `bool` | `true` | no |
| <a name="input_disk_autoresize"></a> [disk\_autoresize](#input\_disk\_autoresize) | Whether if the disk can grow when more space is needed. If disk\_autoresize=true do not set disk\_size as terraform apply would try to set the disk\_size | `bool` | `true` | no |
| <a name="input_disk_type"></a> [disk\_type](#input\_disk\_type) | Type of disk used on the CloudSQL instance VM | `string` | `"PD_SSD"` | no |
| <a name="input_instance_name"></a> [instance\_name](#input\_instance\_name) | Full name of the SQL instance. | `string` | n/a | yes |
| <a name="input_maintenance_window"></a> [maintenance\_window](#input\_maintenance\_window) | Maintenance window to update/patch the VM. It can be rebooted during this maintenance window | <pre>list(object({<br> day = number<br> hour = number<br> update_track = string<br> }))</pre> | `[]` | no |
| <a name="input_module_depends_on"></a> [module\_depends\_on](#input\_module\_depends\_on) | n/a | `any` | `null` | no |
| <a name="input_network"></a> [network](#input\_network) | Self link of the VPC network | `string` | n/a | yes |
| <a name="input_public_ip"></a> [public\_ip](#input\_public\_ip) | assign a public IP to this CloudSQL instance. Attention: you need Security approval to give a public IP to your CloudSQL instance. | `bool` | `false` | no |
| <a name="input_region"></a> [region](#input\_region) | The region to host the resources in. | `string` | `"europe-west1"` | no |
| <a name="input_require_ssl"></a> [require\_ssl](#input\_require\_ssl) | If require SSL, the connection port will be 3307, otherwise 3306. | `bool` | `true` | no |
| <a name="input_tier"></a> [tier](#input\_tier) | CloudSQL instance machine type (service tier). See {Instance settings documentation} | `string` | n/a | yes |
| <a name="input_user_host"></a> [user\_host](#input\_user\_host) | The host the user can connect from. This is only supported for MySQL instances. Don't set this field for PostgreSQL instances. Can be an IP address, or % to allow any host. Changing this forces a new resource to be created. | `string` | `null` | no |
| <a name="input_user_name"></a> [user\_name](#input\_user\_name) | User name. | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_connection_name"></a> [connection\_name](#output\_connection\_name) | Cloud SQL connection name |
| <a name="output_database_name"></a> [database\_name](#output\_database\_name) | Cloud SQL Database name |
| <a name="output_instance_connection_name"></a> [instance\_connection\_name](#output\_instance\_connection\_name) | The connection name of the instance to be used in connection strings. For example, when connecting with Cloud SQL Proxy. |
| <a name="output_instance_ip_address"></a> [instance\_ip\_address](#output\_instance\_ip\_address) | The IPv4 address assigned to the database instance. |
| <a name="output_instance_ip_address_type"></a> [instance\_ip\_address\_type](#output\_instance\_ip\_address\_type) | The type of IP address assigned to this instance. { PRIMARY \| OUTGOING \| PRIVATE }. This module handles with PRIVATE only |
| <a name="output_instance_name"></a> [instance\_name](#output\_instance\_name) | Cloud SQL Database instance name |
| <a name="output_secret_manager_cloudsql_client_cert_secret_id"></a> [secret\_manager\_cloudsql\_client\_cert\_secret\_id](#output\_secret\_manager\_cloudsql\_client\_cert\_secret\_id) | Secret manager id path where the CloudSQL client certificate secret is stored |
| <a name="output_secret_manager_cloudsql_user_secret_id"></a> [secret\_manager\_cloudsql\_user\_secret\_id](#output\_secret\_manager\_cloudsql\_user\_secret\_id) | Secret manager id where the CloudSQL user name/password secret is stored |
<!-- END_TF_DOCS -->
169 changes: 169 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
resource "google_sql_database_instance" "cloudsql_instance" {
name = var.instance_name
region = var.region
database_version = var.database_version

# settings section is optional unless clone is not set. We do not implement clone but insted we create a new instance.
# Thus, settings becomes mandatory in this implementation
# Some of the settigs set are the same as terraform default values but explicitly set
settings {
tier = var.tier
disk_autoresize = var.disk_autoresize
disk_type = var.disk_type

# (backup_configuration is optional)
dynamic "backup_configuration" {
for_each = var.backup_configuration

content {
enabled = backup_configuration.value.enabled
start_time = backup_configuration.value.start_time
location = backup_configuration.value.location
backup_retention_settings {
retained_backups = backup_configuration.value.retained_backups
# retention_unit = "COUNT"
}
}
}

ip_configuration {
# should this cloud sql get assigned a public ip ?
ipv4_enabled = var.public_ip
# VPC network from which cloudsql instance is accessible for private IP.
private_network = var.network
require_ssl = var.require_ssl

# Authorized networks can be configured if:
# - client application is connecting directly to a Cloud SQL instance on its public IP address
# - client application is connecting directly to a Cloud SQL instance on its private IP address,
# and your client's IP address is a non-RFC 1918 address
# ref: # https://cloud.google.com/sql/docs/mysql/authorize-networks
#
# Limitations: addresses that cannot be added as authorized networks
# RFC1918 private addresses (THEY ARE AUTOMATICALLY INCLUDED),
# RFC1122 Loopback, 172.17/16 docker bridge nw,
# RFC3330 null network, RFC3927/2373 link-local, RFC3330/3849 documentation nw,
# RFC3330 multicast networks, class-E address space (RFC1112)
#
# (authorized_networks is optional)
dynamic "authorized_networks" {
for_each = var.authorized_cidrs
iterator = ntw

content {
name = ntw.key
value = ntw.value
}
}
}

# maintenance window (for updates and needed restarts) - Time: UTC, Day: 1-7 (1==Monday,...)
# By default it does maintenance window any time, any day.
# (maintenance_window is optional)
dynamic "maintenance_window" {
for_each = var.maintenance_window
iterator = window
content {
day = window.value.day
hour = window.value.hour
update_track = window.value.update_track
}
}

}

deletion_protection = var.deletion_protection
}

### User

# Password - provide a strong password unless password already provided via variable

# Provide a "Strong" password
# https://dev.mysql.com/doc/refman/8.0/en/validate-password.html
# Note that Password Policy STRONG => lenght>8, 1 numeric + 1 lowercase + 1 uppercase + 1 special, substring of len>=4 are not dictionary words
resource "random_password" "cloudsql_user_password" {
length = 20
special = true
min_lower = 2
min_upper = 2
min_numeric = 2
min_special = 2
override_special = "_%@$#"
}

resource "google_sql_user" "cloudsql_user" {
name = var.user_name
instance = google_sql_database_instance.cloudsql_instance.name
password = sensitive(random_password.cloudsql_user_password.result)
host = var.user_host
}

### Database
resource "google_sql_database" "cloudsql_database" {
name = var.db_name
instance = google_sql_database_instance.cloudsql_instance.name
}

### Certificate
resource "google_sql_ssl_cert" "client_cert" {
common_name = var.cert_common_name
instance = google_sql_database_instance.cloudsql_instance.name
}

### TODO: Secret manager
resource "google_secret_manager_secret" "registry_sql_user_password" {
provider = google-beta
secret_id = "${var.instance_name}_sql_user_password"

replication {
user_managed {
replicas {
location = var.region
}
}
}
}

resource "google_secret_manager_secret_version" "secret-version-basic" {
provider = google-beta
secret = google_secret_manager_secret.registry_sql_user_password.id

secret_data = sensitive(
jsonencode(
{
"cloudsql_instance_name" = google_sql_user.cloudsql_user.instance
"cloudsql_user_name" = google_sql_user.cloudsql_user.name
"cloudsql_user_password" = random_password.cloudsql_user_password.result
}
)
)
}

resource "google_secret_manager_secret" "registry_sql_client_cert" {
provider = google-beta
secret_id = "${var.instance_name}_sql_client_cert"

replication {
user_managed {
replicas {
location = var.region
}
}
}
}

resource "google_secret_manager_secret_version" "registry_sql_client_cert" {
provider = google-beta
secret = google_secret_manager_secret.registry_sql_client_cert.id

secret_data = sensitive(
jsonencode(
{
"cert" = base64encode(google_sql_ssl_cert.client_cert.cert)
"private_key" = base64encode(google_sql_ssl_cert.client_cert.private_key)
"server_ca_cert" = base64encode(google_sql_ssl_cert.client_cert.server_ca_cert)
}
)
)
}
40 changes: 40 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

output "instance_name" {
value = google_sql_database_instance.cloudsql_instance.name
description = "Cloud SQL Database instance name"
}

output "instance_connection_name" {
value = google_sql_database_instance.cloudsql_instance.connection_name
description = "The connection name of the instance to be used in connection strings. For example, when connecting with Cloud SQL Proxy."
}

output "instance_ip_address" {
value = google_sql_database_instance.cloudsql_instance.ip_address
description = "The IPv4 address assigned to the database instance."
}

output "instance_ip_address_type" {
value = google_sql_database_instance.cloudsql_instance.ip_address[0].type
description = "The type of IP address assigned to this instance. { PRIMARY | OUTGOING | PRIVATE }. This module handles with PRIVATE only"
}

output "database_name" {
value = google_sql_database.cloudsql_database.name
description = "Cloud SQL Database name"
}

output "connection_name" {
value = google_sql_database_instance.cloudsql_instance.connection_name
description = "Cloud SQL connection name"
}

output "secret_manager_cloudsql_user_secret_id" {
value = google_secret_manager_secret.registry_sql_user_password.secret_id
description = "Secret manager id where the CloudSQL user name/password secret is stored"
}

output "secret_manager_cloudsql_client_cert_secret_id" {
value = google_secret_manager_secret.registry_sql_client_cert.secret_id
description = "Secret manager id path where the CloudSQL client certificate secret is stored"
}
Loading

0 comments on commit 41536ee

Please sign in to comment.