2

Trying to setup connection to Clond SQL 2nd Generation for a Java Appengine with Managed VM.

What I got:

  • VM is using Appengine Compat mode (FROM gcr.io/google_appengine/java-compat)
  • I see a MySQL pipe on the host (SSHed, I can see /cloudsql/** socket), but default MySQL Java driver doesnt support unix sockets
  • Google Driver seems to be unsupported on Managed VM (java.lang.ClassNotFoundException: com.mysql.jdbc.GoogleDriver)
  • and I cannot connect to MySQL by IP
    • w/o driver it's No suitable driver found for jdbc:google:mysql://__IP__:3306/__db__
    • or timeout for jdbc:mysql://__IP__:3306/__db__ (I've added MVM external IP to authorized networks on MySQL)
    • but what interesting, I can connect to this port from MVM machine, at least port is opened. Anyway, I don't like idea of connecting through publicly open IP:PORT. MVM have a new IP each time, so I even can't add a Firewall rule to specify access from my project only

How I should configure ManagedVM app to connect to Cloud SQL?

Igor Artamonov
  • 35,450
  • 10
  • 82
  • 113
  • Probably you will not be able to connect internally because Cloud SQL 2nd gen doesn't currently support App Engine. If you are able to connect with a mysql client from the Managed VM you should be able to connect with the external ip+user+password. But maybe you have to install an driver not patched by Google? App Engine doesn't support connecting to external SQL either... – dyeray Jan 15 '16 at 08:59
  • as I understand, CloudSQL Proxy (https://github.com/GoogleCloudPlatform/cloudsql-proxy ) that enabled on my MVM, it supports proxying to `localhost:3306`. Currently it creates only a unix socket, not port. I guess it's default config, and I probably need to add some configuration to open port as well. still investigating how I can do that – Igor Artamonov Jan 15 '16 at 12:30
  • I am not sure how CloudSQL Proxy works, but as I said, Cloud SQL 2nd gen is not available currently on Appengine so you would have to connect to the public IP of the Cloud SQL instance with a regular MySQL driver. – dyeray Jan 15 '16 at 13:16
  • Cloud SQL 2nd works through Unix pipe, see https://cloud.google.com/sql/docs/sql-proxy . Problem with public IP is that I need to install private SSL keys into JVM. I guess it's possible to do with custom mvm image, but that's too much, and forces me to put secret keys under Source Version Control. So I think if we have cloud-sql-proxy already, supported by google, deployed to MVM already, that works fine for Python MVM, and compatible with Java as I see in source code, so it's better to use it from Java too, as a standard tool. the question now is how to run it with proper args – Igor Artamonov Jan 15 '16 at 13:33
  • found that mvm scripts has blocked all ways to enable port forwarding for sql-proxy, which can easily fix this. maybe on purpose, maybe just a mistake, maybe authors just fighting against Java, but hope it's will be fixed soon. seems that for now the only way is custom docker image with SSL keys, and mysql opened to whole range of google ips :( – Igor Artamonov Jan 15 '16 at 15:00

3 Answers3

1

I am having trouble launching a Managed VM App using Java so I can't try it out for myself right now, but it looks like you should be able to leverage this library to connect to a Unix Socket from Java. There's an example in which you'd just have to change the path of the socket:

props.put("junixsocket.file", "/cloudsql/project-id:region:instance-id");

Where project-id is your project name, region is the region in which your Cloud SQL instance lives (e.g. us-east1) and instance-id is the name of your cloud-sql instance. The string will be in the properties of your Second Generation instance under "Instance connection name".

  • yeah, i thought about this. but it requires installing binary `.so` into VM, and also I worried about lib license type. I decided to use SSL instead, still requires custom VM though – Igor Artamonov Jan 16 '16 at 11:06
  • The license appears to be Apache 2, which is usually considered relatively permissive. I'm not a lawyer, but my layman's understanding is that you can use the software in a server context without any issues. (If this is for commercial use you should verify with some real lawyers first.) – Kevin Malachowski Jan 17 '16 at 01:23
  • oh, i see. sorry, my mistake. i found similar lib before your answer (it looked similar, so I just confused them). that lib was GPL/LGPL licensed. sorry for confusion. – Igor Artamonov Jan 17 '16 at 08:51
1

We have a new Java library for connecting to Cloud SQL instances from Managed VMs and other environments: https://github.com/GoogleCloudPlatform/cloud-sql-mysql-socket-factory

It's still very new so the usual caveats apply, but we haven't found any issues in our testing.

Vadim
  • 4,996
  • 1
  • 26
  • 30
  • Just tried it out and it works flawlessly for me. Maybe you should mention it in the docs? Currently they say cloud sql is not supported for java apps https://cloud.google.com/appengine/docs/flexible/java/using-cloud-sql – Gabriel Ittner Apr 12 '16 at 18:29
  • Thanks. we're definitely going to add it to the docs! We have been gathering feedback from early customers prior to publicizing it to a wider audience. – Vadim Apr 13 '16 at 08:55
  • Is there a solution [to this](http://stackoverflow.com/questions/37644148/java-lang-illegalstateexception-could-not-load-jdbc-driver-class-com-mysql-jdb)? :/ – Stefan Falk Jun 05 '16 at 18:40
0

Best way I found is to configure SSL connection from ManagedVM

There two things you should do.

First, prepare Java Keystore with SSL you'll get from Cloud SQL console (files server-ca.pem, client-cert.pem and client-key.pem):

echo '---------- GENERATE TrustStore'
keytool -import -alias mysqlCACert -file server-ca.pem -keystore truststore -storepass 123456

echo '---------- GENERATE KeyStore'
openssl pkcs12 -export -in client-cert.pem -inkey client-key.pem \
    -out client.p12 -name clientalias -CAfile server-ca.pem -caname root
keytool -importkeystore -deststorepass 123456 -destkeystore keystore \
    -srckeystore client.p12 -srcstoretype PKCS12 -srcstorepass 123456 -alias clientalias

You'll get two files: truststore and keystore that you'll need to put into your target VM.

Second, you should use custom Dockerfile, with files from previous step:

FROM gcr.io/google_appengine/java-compat

RUN mkdir /keys
ADD keystore /keys/
ADD truststore /keys/
ENV JAVA_OPTS -Djavax.net.ssl.keyStore=/keys/keystore -Djavax.net.ssl.keyStorePassword=123456 -Djavax.net.ssl.trustStore=/keys/truststore -Djavax.net.ssl.trustStorePassword=123456

ADD .  /app/

And, of course, don't forget to tell MySQL driver to always use SSL:

dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://__CLOUD_SQL_IP__:3306/__CLOUD_SQL_DB__?useSSL=true&requireSSL=true");

PS Notice, I'm using password 123456 to protect my keys. It's just example. Don't use it in your project. It's already taken.

Igor Artamonov
  • 35,450
  • 10
  • 82
  • 113
  • FYI we have a beta release of a small library to make it easier to connect from Java applications. I know you already have things working, but if you're interested please give it a shot: https://github.com/GoogleCloudPlatform/cloud-sql-mysql-socket-factory – Vadim Mar 28 '16 at 23:35