5

I have a Java web app running on AWS and connecting to a MySQL database running on AWS RDS.

My app uses SSL client certificates signed by our own CA to connect to various web services, so I have set the -Djavax.net.ssl.keyStore and -Djavax.net.ssl.trustStore system properties.

I have added the https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem certificates to my trustStore, and I can connect to MySQL fine using SSL via the command-line client.

My MySQL connection string looks like:

jdbc:mysql://my-server-id.eu-west-1.rds.amazonaws.com/my-database?verifyServerCertificate=true&useSSL=true&requireSSL=true

I am using mysql:mysql-connector-java:jar:5.1.38 to run the JBDC connection.

I have found that my Java app can connect OK to MySQL when I set the trustStore, but it fails when I set the keyStore and the trustStore:

! javax.net.ssl.SSLException: Unsupported record version Unknown-0.0
! at sun.security.ssl.InputRecord.checkRecordVersion(InputRecord.java:552) ~[na:1.8.0_91]
! at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:565) ~[na:1.8.0_91]
! at sun.security.ssl.InputRecord.read(InputRecord.java:532) ~[na:1.8.0_91]
! at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) ~[na:1.8.0_91]
! at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) ~[na:1.8.0_91]
! at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403) ~[na:1.8.0_91]
! at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387) ~[na:1.8.0_91]
! at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:149) ~[user-portal-web-0.0.1.jar:0.0.1]
! ... 40 common frames omitted

It seems that Java is presenting my private-CA signed client cert to MySQL, which is rejecting it. I have captured the interaction using tcpdump, and the DN of my client cert is being sent to MySQL.

How can I use my client cert for HTTPS connections, but not use it for the MySQL connection?

I have tried creating an empty keystore and setting my connection string to use it:

jdbc:mysql://my-server-id.eu-west-1.rds.amazonaws.com/my-database?verifyServerCertificate=true&useSSL=true&requireSSL=true&clientCertificateKeyStoreUrl=file:nokeys.jks&clientCertificateKeyStorePassword=changeit

That gives me the following error:

java.lang.IllegalStateException: TrustManagerFactoryImpl is not initialized
    at sun.security.ssl.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:100)
    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:285)
    at com.mysql.jdbc.ExportControlled.getSSLSocketFactoryDefaultOrConfigured(ExportControlled.java:323)
    at com.mysql.jdbc.ExportControlled.transformSocketToSSLSocket(ExportControlled.java:85)
4

You can force MySQL to use no client certificate by setting an empty keystore in the connection URL.

The problem I had above was a variant of https://bugs.mysql.com/bug.php?id=36948 -- if you set "clientCertificateKeyStoreUrl" in the connection URL but not also "trustCertificateKeyStoreUrl" (and the 4 other params below), then MySQL will crash with "TrustManagerFactoryImpl is not initialized" instead of a more helpful error.

You can create an empty keystore with a command like:

keytool -genkey -alias foo -keystore empty.jks # (set password "changeit")
keytool -delete -alias foo -keystore empty.jks

Then connect to MySQL with a URL like:

jdbc:mysql://my-server-id.rds.amazonaws.com/my-database?verifyServerCertificate=true&useSSL=true&requireSSL=true&clientCertificateKeyStoreUrl=file:empty.jks&clientCertificateKeyStorePassword=changeit&clientCertificateKeyStoreType=JKS&trustCertificateKeyStoreUrl=file:/etc/pki/cosmos/current/client.jks&trustCertificateKeyStoreType=JKS&trustCertificateKeyStorePassword=changeit

All 6 keystore args are required, even if you want the defaults, otherwise you will see the "TrustManagerFactoryImpl is not initialized" error

  • Additionally, you can just leave off the 3 clientCertificate... params from the JDBC URL and it also connects. This is with version 5.1.40. It solves the infamous SSLException: Unsupported record version Unknown-0.0. – Adam May 10 '17 at 15:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.