mba12 mba12 - 1 year ago 185
MySQL Question

Google Cloud SQL with SSL from Compute Engine and/or External Network

I'm trying to connect to an Google Cloud SQL (mysql) instance using SSL. I've enabled two IP addresses and a user with remote access permissions from those IP addresses. I have also generated the certificate files from Google's Developer Console.

client-key.pem client-cert.pem server-ca.pem

Using this command from each of the two enabled IP addresses I successfully make a connection.

mysql --ssl-ca=server-ca.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem --user=username --password

Since the mysql client works I know my firewall settings, users, certs, etc. are set up correctly.

Now I'd like to make a similar connection with java from within an executable jar file.

Following the steps outlined here:

Step 1: keytool -import -alias mysqlServerCACert -file cacert.pem -keystore truststore

NOTE: I substitute server-ca.pem for cacert.pem used in the instructions

Step 2: openssl x509 -outform DER -in client-cert.pem -out client.cert
Step 3: keytool -import -file client.cert -keystore keystore -alias mysqlClientCertificate

These steps create my keystore and truststore files. I associate distinct passwords for
each of these two files as they are generated.

Here is the relevant Java code:

public void testConnection() throws ClassNotFoundException, SQLException,
IllegalAccessException, InstantiationException {

String path = "/home/user/dir/"; // path to keystore and truststore file

System.setProperty("",path + "keystore");
System.setProperty("",path + "truststore");

String user = "dbuser";
String password = "dbUserPassword";

Connection conn = null;
int i = 0;
try {
String url = "jdbc:mysql://<databaseip>:3306/<databaseName>"
+ "?verifyServerCertificate=true"
+ "&useSSL=true"
+ "&requireSSL=true";

Class dbDriver = Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);

ResultSet rs = conn.createStatement().executeQuery(
"SELECT 1 + 1 as val");

while ( {
i = rs.getInt(1);
} catch (Exception ex) {
} finally {
if (conn != null) {
try {
} catch (Exception e) {
System.out.println("The MySQL value is: " + i);

Again, from both enabled IP addresses I am able to connect with the MySQL command line client with the same user and password being used in the java code.

I receive the following connection exception with the java. Given that the mysql client works with the same user/passwd credential I am a bit suspect of the error message. Any insights much appreciated. Has anyone else got SSL up and working with Google SQL? Thoughts, advice, tricks and tips appreciated. Thanks!

java.sql.SQLException: Access denied for user 'dbuser'@'' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(
at com.mysql.jdbc.MysqlIO.checkErrorPacket(
at com.mysql.jdbc.MysqlIO.checkErrorPacket(
at com.mysql.jdbc.MysqlIO.secureAuth411(
at com.mysql.jdbc.MysqlIO.negotiateSSLConnection(
at com.mysql.jdbc.MysqlIO.doHandshake(
at com.mysql.jdbc.Connection.createNewIO(
at com.mysql.jdbc.Connection.<init>(
at com.mysql.jdbc.NonRegisteringDriver.connect(
at java.sql.DriverManager.getConnection(
at java.sql.DriverManager.getConnection(
at com.test.UserData.getConnection(
at com.test.UserData.testConnection(

Answer Source

mba12 I had the same problem, thanks for the answer!

So, the solution is here (as you pointed out): How to connect to MySQL with X509 using JDBC?

I also found this one: importing an existing x509 certificate and private key in Java keystore to use in ssl

Just for clarification must be client cert + key combined, not just client cert as described in MySQL guide.

To summarize

  1. We have:

server-ca.pem - MySQL CA certificate, can be downloaded from "SSL Configuration -> View Server CA Certificate"

client-cert.pem - client public key, can be downloaded from "Client Certificates -> newly created certificate"

client-key.pem - client private key, can be downloaded only from "New SSL Certificate created dialog box"

Described here:

Let's save them in server-instance/ folder and create jks/ folder for generated files in step 2.

  1. Create truststore file

    2.1. Copy original JAVA's cacerts to jks/truststore.jks:

    cp $JAVA_HOME/jre/lib/security/cacerts jks/truststore.jks

    2.2. Add MySQL Server CA Certificate / Google Cloud SQL Server CA server-ca.pem to JAVA's default truststore cacerts which we've copied in step 2.1.:

    keytool -importcert -noprompt -trustcacerts -keystore jks/truststore.jks -storepass changeit -alias googlecloudsqlservercacert -file server-instance/server-ca.pem

  2. Create keystore file

    3.1. Convert x509 certificate and private key to a pkcs12 file:

    openssl pkcs12 -export -in server-instance/client-cert.pem -inkey server-instance/client-key.pem -out jks/client.p12

    (enter mandatory password), for example: p4ssw0rd

    3.2. Convert the pkcs12 file to a java keystore:

    keytool -importkeystore -srckeystore jks/client.p12 -srcstoretype PKCS12 -destkeystore jks/keystore.jks -deststoretype JKS

    (enter same passwords), for example: p4ssw0rd

About conversion:

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download