Enforcing SSL
Part of Working with Cloud SQL
Tutorial
- Setting up the Cloud SQL instance
- Creating a Compute Engine instance for testing
- Validating connectivity using an unencrypted connection
- Whitelisting the Compute Engine instance IP address in Cloud SQL
- Validating connectivity with an unencrypted connection (attempt 2)
- Enforcing SSL connections in our Cloud SQL instance
- Connecting to the instance using Mutual SSL
In this first part of the Working with Cloud SQL series, we will see how we can secure a Cloud SQL instance by explicitly disallowing unencrypted connections. Let's first create a Cloud SQL instance that we can use for experimentation.'
Setting up the Cloud SQL instance
Navigate to the Cloud SQL dashboard in the Google Cloud Console: https:
Select 'Create Instance'.
Choose 'MySQL' as the database engine.
On the page that opens provide the following details:
- Enter a unique instance name
- Enter a secure root user password for the instance
- Set the database version to 'MySQL 8.0'.
- Choose 'sandbox' as the default configuration
- Choose a region close to you
- Disable 'Deletion protection' in case you want to easily delete the instance after this tutorial
Wait for the instance creation to complete. This can take a few minutes.
Creating a Compute Engine instance for testing
Navigate to the Compute Engine dashboard: https:
Select 'Create Instance'.
Enter an instance name
Choose a Region and Zone close to you
Choose the 'N1' family and then choose 'f1-micro' as the machine type
Under 'Boot disk', click 'Change'.
Choose 'Ubuntu' as the 'Operating system'.
Choose 'Ubuntu 22.04 LTS' as the 'Version'.
As boot disk type, choose 'Standard Persistent Disk'.
As disk size, select '10' GB.
Under 'Identity and API access', select 'No service account'.
Click 'Create'.
Wait for the instance creation process to complete.
Validating connectivity using an unencrypted connection
In the Compute Engine dashboard, use the 'SSH' button to open an SSH session.
Update the APT caches:
sudo apt update
Install the MySQL Client:
sudo apt install mysql-client
When prompted, confirm that you want to install the tools by entering Y and pressing ENTER.
Verify the MySQL version:
mysql --version
The output should look like this:
mysql Ver 8.0.33 for macos13.3 on x86_64
Let's now try to connect to our Cloud SQL instance:
mysql -h <ip-address> -u root -p
When prompted enter the password of the root user.
Unfortunately, the connection hangs. Press CTRL+C to cancel the connection attempt. The reason for the connection failure is that we haven't whitelisted our Compute Engine instance's IP on our Cloud SQL instance. By default, Cloud SQL blocks internet access from all IPs.
Whitelisting the Compute Engine instance IP address in Cloud SQL
Close the SSH session for now, or minimize the window.
In the Compute Engine dashboard click on the three dots at the end of the row (see image), and select 'View network details'.
On the 'Network interface details' page, copy the 'External IP address' value.
Navigate to the Cloud SQL instance dashboard: https:
Select your Cloud SQL instance.
In the sidebar, select 'Connections'.
Open the 'Networking' tab.
Under 'Authorized networks', click on 'Add a network'.
Give the network a name. (e.g. Compute Engine instance) Choose a descriptive name here, so you remember later on why you whitelisted this IP address.
In the 'Network' text field, paste the IP address you copied earlier and append /32
. So the IP address should look like 123.123.123.123/32
.
Click on 'Done' to confirm the whitelisting.
Click 'Save' to apply the changes to the Cloud SQL instance.
Wait a few minutes for the instance to be updated.
Validating connectivity with an unencrypted connection (attempt 2)
Reopen your SSH session to the Compute Engine instance.
Run the mysql
command again to retry connectivity:
mysql -h <ip-address> -u root -p
When prompted enter the password of the root user.
We can now connect to our instance!
Depending on the MySQL client version that you are using the connection is either encrypted or unencrypted. Newer versions of the MySQL Client try to use an encrypted connection by default, but fall back to an unencrypted connection if no connection can be otherwise established. If our connection is unencrypted, a malicious actor could intercept our network traffic and potentially extract confidential information.
Let's now see how we can make sure encrypted connections are enforced by the server.
Enforcing SSL connections in our Cloud SQL instance
Navigate to the Cloud SQL instance dashboard: https:
Select your Cloud SQL instance.
In the sidebar, select 'Connections'.
Open the 'Security' tab.
Under 'SSL encryption', check the 'Allow only SSL connections' flag.
A dialog shows, asking you if you want to restart the instance. Select 'Save & restart'. (Don't do this on a production instance without scheduling the downtime)
Wait a few minutes for the instance to be restarted.
Now that we've checked the 'Allow only SSL connections' flag, Google Cloud will not only enforce encrypted connections, but it will require us to authenticate with a Client Certificate in addition to the password that we already provide. This functions as a second factor of authentication and provides another layer of security for our Cloud SQL instance.
Before we can connect though, we need to generate a Client Certificate.
Click on the 'Create client certificate' button under 'Manage client certificates'.
Give the certificate a descriptive name.
Download the different certificates that are displayed. You will need all three values to connect to the instance.
Connecting to the instance using Mutual SSL
Upload the certificate files to the Compute Engine instance.
Use the certificates to establish a secure connection to the Cloud SQL instance:
mysql -h <ip-address> --ssl-ca=server-ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem --ssl-mode=VERIFY_CA -u root -p
In the above command we provide the MySQL Client with the following details:
- We provide a
server-ca.pem
file that can be used to validate that the Cloud SQL instance is our actual instance and not some malicious server that is acting like our instance. - We provide a
client-cert.pem
, which the server can use to validate our identity. - We provide a
client-key.pem
file that the client can use to further prove that we are authorized. - We set the SSL mode to VERIFY_CA, so that the MySQL client validates the server certificate (by default this is not necessarily the case, it depends on the version that you have installed).
Press ENTER to establish a connection.
We are successfully able to connect.
Finally, let's try to connect without providing all these certificates:
mysql -h <ip-address> -u root -p
As expected, MySQL is denying us access to the instance.