简体   繁体   中英

Disable mySQL RDS client authentication

I am trying to connect to a mySQL RDS DB from a java SpringBoot application. I have made the required changes on the DB.

ALTER USER 'my_app'@'%' require SSL;
GRANT USAGE ON *.* TO 'my_app'@'%' REQUIRE SSL;

However, the connection does not happen. It is failing at the client authentication part. The server (mysql db) is not able to authenticate the client (java application).

Question:

  • How do I disable client authentication? Based on the documentation it should be disabled unless you do "REQUIRE X509". So, I am confused about that. Documentation I am referring is this: https://dev.mysql.com/doc/refman/8.0/en/alter-user.html .

  • How can I make this work, using both a keyStore and trustStore?

More info:

I have also imported the AWS root and regional certificate into my trust store. At this point (without a keyStore passed as JVM), the connection happens fine.

However, in my application I need to use a keyStore as well.

 -Djavax.net.ssl.keyStore=path/keyStore.jks
 -Djavax.net.ssl.keyStorePassword=<keyStore_password>

When, I do this, the connection does not happen and the following error is thrown:

main, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

Adding the ssl handshake debug I see the following logs:

*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<Empty>
localhost-startStop-1, READ: TLSv1.1 Handshake, length = 4
*** ServerHelloDone
matching alias: mysqlrds
matching alias: client-nonprod
*** Certificate chain
chain [0] = [

It looks like it is failing at the part where the server (mysql DB) is trying to verify the client (java application). In the following steps the client (java application) needs to present a certificate to the server (mysql db).

In the step above (CertificateRequest), the server is sending an empty "Cert Authorities". Which usually means that the server (mysql db) has an empty or not initialize trust store. The steps afterwards (Certificate chain), the client (java app) send to the server (mysql db) a certificate. In this case the "keyStore_cert.jks". But the server, does not know about it and it throws and error on Handshake.

Sample Code:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

//1. Dowload my sql connector to a folder "jars". http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar
//   This file and the jars folder are on the same folder (or level). Not inside one another.
//2. edit this file to have your settings. Name of the DB,URL,username,password,trustStore,keyStore,DB name, table name.
//3. compile the file:  javac -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode.java
//4. run the program:   java -cp ".:./jars/mysql-connector-java-8.0.13.jar"  SampleCode

public class SampleCode {
  public static void main(String[] args) {
    Connection con;
    try {
      // TODO: replace with your settings.
      System.setProperty("javax.net.ssl.trustStore", "path/resource/certs/trustStore.jks");
      System.setProperty("javax.net.ssl.trustStorePassword", "trustStore_pass");
      System.setProperty("javax.net.ssl.keyStore", "path/resource/certs/keyStore.jks");
      System.setProperty("javax.net.ssl.keyStorePassword", "keyStore_pass");
      System.setProperty("javax.net.debug", "ssl:handshake");

      Class.forName("com.mysql.cj.jdbc.Driver");
      // TODO: replace with your settings.
      con = DriverManager.getConnection(
          "jdbc:mysql://my_db_name.random_string.us-east-1.rds.amazonaws.com:3/my_db?useLegacyDatetimeCode=false&verifyServerCertificate=true&useSSL=true&requireSSL=true",
          "my_app", "my_pass");

      System.out.println(" connection successful \n");
      Statement stmt = con.createStatement();
      ResultSet rs = stmt.executeQuery("SELECT * FROM my_table "); // TODO: replace with yours.
      while (rs.next()) {
        System.out.println("id : " + rs.getString("id"));
      }

      rs.close();
      stmt.close();
      con.close();
    } catch (Exception e) {
      System.out.println(e);
    }
  }
}

Reference Materials:

I faced this same error in an application where hibernate is used. Apparently RDS only does client authentication during a SSL handshake. Instead of disabling client authentication because you need to use a separate key store for your application you can override the key store used for jdbc connection through connection properties.

  1. Follow the steps mentioned in section "Updating your application trust store for JDBC" at https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/ssl-certificate-rotation-mysql.html to get the client keystore that will be used for RDS connection.
  2. Add the following code in you sample code:
Properties properties = new Properties();
properties.put("user", "my_app");
properties.put("password", "my_pass");  properties.put("clientCertificateKeyStoreUrl","file:path_to_rds_truststore_file");
properties.put("clientCertificateKeyStorePassword","password");
 String url = "jdbc:mysql://localhost/mydatabase";
Connection con = DriverManager.getConnection(url, properties); 

By doing the above you can override the keystore that will be used for establishing connection to RDS while using a separate system wide keystore. Note that you need to set the properties every time you want to get a connection to the RDS instance.

As mentioned in your reference :

Notice that when used together, the connection properties override the values set by the other two methods. Also, whatever values set with connection properties are used in that connection only, while values set using the system-wide values are used for all connections (unless overridden by the connection properties).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM