31
Securing sensitive data in Cloud SQL
In the previous part we created our GKE Autopilot cluster. In this part we will configure the Cloud SQL Instance.
The following resources will be created:
- A highly available private Cloud SQL MySQL Instance
- A database and a user
- An automatic internal IP range for private connection
- A private connection to GCP services
- The Cloud SQL Instance used is a MySQL database server
- The
Multiples zones
option is enabled to ensure high-availability - The Instance is not publicly accessible and it's reachable only using its private IP
- The authentication is done via IAM
- Automated backup is enabled
- We create a database and a user for later
Create a terraform file infra/plan/cloud-sql.tf
resource "random_string" "db_name_suffix" {
length = 4
special = false
upper = false
}
resource "google_sql_database_instance" "mysql" {
# Instance info
name = "mysql-private-${random_string.db_name_suffix.result}"
region = var.region
database_version = var.mysql_database_version
settings {
# Region and zonal availability
availability_type = var.mysql_availability_type
location_preference {
zone = var.mysql_location_preference
}
# Machine Type
tier = var.mysql_machine_type
# Storage
disk_size = var.mysql_default_disk_size
# Connections
ip_configuration {
ipv4_enabled = false
private_network = google_compute_network.custom.id
}
# Backups
backup_configuration {
binary_log_enabled = true
enabled = true
start_time = "06:00"
}
}
depends_on = [
google_service_networking_connection.private-vpc-connection
]
}
data "google_secret_manager_secret_version" "wordpress-admin-user-password" {
secret = "wordpress-admin-user-password"
}
resource "google_sql_database" "wordpress" {
name = "wordpress"
instance = google_sql_database_instance.mysql.name
}
resource "google_sql_user" "wordpress" {
name = "wordpress"
instance = google_sql_database_instance.mysql.name
password = data.google_secret_manager_secret_version.wordpress-admin-user-password.secret_data
}
Add the following outputs
output "cloud-sql-connection-name" {
value = google_sql_database_instance.mysql.connection_name
}
output "cloud-sql-instance-name" {
value = "mysql-private-${random_string.db_name_suffix.result}"
}
We need to configure private services access to allocate an IP address range and create a private service connection. This will allow resources in the Web subnet to connect to the Cloud SQL instance.
Complete the file infra/plan/vpc.tf
with the following resources:
resource "google_compute_global_address" "private-ip-peering" {
name = "google-managed-services-custom"
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 24
network = google_compute_network.custom.id
}
resource "google_service_networking_connection" "private-vpc-connection" {
network = google_compute_network.custom.id
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = [
google_compute_global_address.private-ip-peering.name
]
}
Complete the file infra/plan/variable.tf
:
variable "region" {
type = string
default = "europe-west1"
}
variable "mysql_location_preference" {
type = string
default = "europe-west1-b"
}
variable "mysql_machine_type" {
type = string
default = "db-n1-standard-2"
}
variable "mysql_database_version" {
type = string
default = "MYSQL_8_0"
}
variable "mysql_default_disk_size" {
type = string
default = "100"
}
variable "mysql_availability_type" {
type = string
default = "REGIONAL"
}
Before applying the changes, we need to create the secret of the user password:
gcloud services enable secretmanager.googleapis.com --project $PROJECT_ID
gcloud beta secrets create wordpress-admin-user-password --locations $REGION --replication-policy user-managed
echo -n "changeme" | gcloud beta secrets versions add wordpress-admin-user-password --data-file=-
Let's deploy our Cloud SQL instance
cd infra/plan
gcloud services enable sqladmin.googleapis.com --project $PROJECT_ID
terraform apply
Let's check if all the resources have been created and are working correctly:
Cloud SQL instance
Peering connection
Private connection
Our Cloud SQL instance is now available. In the last part, we'll establish a connection between a container deployed in GKE cluster and a database created in an Cloud SQL instance.
31