The Microsoft JDBC SSL documentation details the use of a Java keystore in order to specify a certificate bundle to use when validating the TLS connection. Is there a way to provide a certificate bundle without needing to store it within a JKS when connecting to a SQL Server database? Postgres seems to have a sslrootcert option which appears to be lacking for SQL Server.
Since version 6.3.3 the Microsoft JDBC Driver for SQL allows, to specify a custom implementation of javax.net.ssl.TrustManager through connection properties. You can specify a class name and a constructor parameter (e.g. a file name or the certificate in PEM format).
See here, for more detailed instructions and a simple example of a custom TrustManager. The functionality of the sslrootcert option of the Postgres driver is implemented in a similar way here.
Related
The problem that we are facing is well documented in https://stackoverflow.com/questions/34189756/warning-about-ssl-connection-when-connecting-to-mysql-database.
We started facing this issue upon transitioning from MySQL 5.6.51 to MySQL 8.0.27.
The fix that is suggested works for us but we have an issue in that we don’t want to update the Java source files to change, for example, from
jdbc:mysql://localhost:3306/Peoples
to
jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false
as suggested in https://stackoverflow.com/a/34449182
Question: Is there some change that we can make to the execution environment of our new target (Ubuntu kernel version 5.4.0-91) such that we need not make changes to the existing Java code?
You could resolve the SSL errors using the other method recommended in the error message itself:
You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
(emphasis mine)
That is, create a truststore file, and set the path to the truststore file and the password using Java properties. Then you can set those properties without changing code.
See https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-using-ssl.html for more details on creating the truststore file and use properties to specify it to your Java app.
I am able to connect to HANA database through my server using JDBC. I am trying to figure out if my connection to the database is secured or not?
public void createDataSource() {
DataSource dataSource = DataSourceBuilder.create()
.driverClassName(JDBC_DRIVER)
.URL("jdbc:sap://localhost:30013/?encrypt=true&validateCertificate=true")
.username("username")
.password("password")
.build();
Connection c = dataSource.getConnection();
}
Now what I have understood from Documentation is that when I set parameters in the URL such
encrypt=true
It enables or disables TLS encryption.
For SAP HANA Cloud connections to succeed, encrypt must be set to TRUE.
Another parameter is:
validateCertificate=true
If set to true, specifies that the server’s certificate is validated.
Here I am not able to understand is when it will be deployed to production is this all we need to do for a secure database connection? Can someone please point out what I am missing?
The neat thing about certificates is that you normally don't have to worry about them.
The java virtual machine (JVM) ships with a set of so-called root certificates of the certificate authorities (CAs) (including the DigiCert Global Root CA). Depending on the java distribution there might be slight differences, but the top CAs should be trusted by all.
You can see the list of trusted CAs with the following command:
keytool -list -v -cacerts -storepass changeit
As long as the SSL certificate of your database is signed by one of these CAs (or an intermediate of these) you don't need any additional configuration and it just works out of the box. This is as well the scenario, which you should aim for as it is the easiest.
You can however as well pass to the JVM your own list of trusted certificates or, and this is probably for a generic set up the best, set a custom truststore for a single JDBC connection. In a dockerized setup, you can e.g. make the whole database string configurable allowing people to mount their own CAs into the container and configure them in the database connection string. For details check the SAP documentation on the "JDBC Connection Properties for SAP HANA".
jdbc:sap://localhost:30013/?encrypt=true&validateCertificate=true&trustStore=file:cert/truststore.jks&trustStorePassword=123456
We have a java client (mule app) which is using JTOpen for connecting to the AS400 system.
The connection is secured with SSL. The driver is using the JRE truststore (jssecacerts, cacerts) by default.
We would like to specify a custom truststore for the JTOpen session.
The only way to do this that I found in the documentation is to configure the javax.net.ssl.trustStore system property.
But this is a global property that may affect other applications. So, we are looking for the alternative.
Is there another way of specifying a path to a truststore for JT400, so, that it would not affect other applications running on the same VM system? May be a connection parameter or the driver specific property?
We have a remote PostgreSQL DB server which requires SSL certs to be provided to connect to it.
I have the following certs with me.
root.pem
intermediate.pem
private-chain.pem
public-chain.pem
certificate.cer
certificate.key
And I am able to connect to the remote database using psql as
psql "port=5432 host=remote-host user=username sslcert=public-chain.pem sslkey=certificate.key dbname=database sslmode=require"
Now, I need to connect to the same database from a Java Spring based Rest API. So, ideally this would require building keystrokes from the certs and using that to connect to the the db.
The issue is, I'm not able to! I've tried all combinations of cert, public-chain, private-chain, root ca, etc. in the keystore. And I've tried passing the keystore as JVM arguments when calling the jar file (-Djavax.net.ssl.trustStore -Djavax.net.ssl.trustStorePassword -Djavax.net.ssl.keyStore -Djavax.net.ssl.keyStorePassword).
I've also tried pointing to the keystrokes from PostgreSQL JDBC connection string (jdbc:postgresql://remote-host:5432/database?ssl=true&sslcert='filename'&sslkey='key'). Not really sure if this is the right way.
But I keep getting this error.
Caused by: org.postgresql.util.PSQLException: FATAL: connection requires a valid client certificate
at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:473) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:205) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.Driver.makeConnection(Driver.java:452) ~[postgresql-42.2.2.jar!/:42.2.2]
at org.postgresql.Driver.connect(Driver.java:254) ~[postgresql-42.2.2.jar!/:42.2.2]
I am not able to figure out why it works with psql and not with jdbc.
EDIT 1:
Currently I am trying the following approach. This is the spring datasource configuration
spring.datasource.url=jdbc:postgresql://remote-host:5432/database?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory
spring.datasource.username=username
This is the cert config
export PGSSLCERT=/tmp/client.cer
export PGSSLKEY=/tmp/client.key
export PGSSLMODE=allow
I've also followed the steps described here to trust root ca. But I guess that is not necessary since I'm using org.postgresql.ssl.NonValidatingFactory
And I'm starting the application as
java -jar -Dspring.profiles.active=prod application.jar
Any insights into this are appreciated! Thanks.
What does your pb_hba.conf setting look like?
The JDBC driver only supports the trust, ident, password, md5, and crypt authentication methods.
So your java app will have to connect using password and certificate. You can specify that in your pb_hba.conf:
hostssl all all 0.0.0.0/0 md5 clientcert=1
I am trying to create a java application that uses PKI for authentication. I need to be able to retrieve a certificate from the Microsoft Certificate Store (MCS) and pass it along to an Oracle database (11.2).
I am connecting using the jdbc:oracle:thin driver. After spending quite some time on google I have come up empty.
I've found different properties to change (depending on the article):
set the property javax.net.ssl.keyStoreType = "Windows-MY"
set the javax.net.ssl.keyStore = "Windows-MY"
javax.net.ssl.keyStore should be set to "None" (if using a custom KeyManager which I do not believe will work since by the time it gets into my custom KeyManager I will already be given the certs from a keystore specified in the connection properties).
Of course all of these people are claiming success, but nothing has worked for me. I have tried every example I have been able to find all with no luck. I was able to successfully authenticate when I was using Oracle wallets so I know my certificates are fine. If anyone has done this before and is willing to post some code that would be great.
I know most people are using the Windows keystore with a website and therefore are creating their own SSLContext, but I cannot imagine I am the only one who has wanted to do this using JDBC (which as far as I know does not allow me to provide it an SSLContext).
This is the code that I believe should work, but does not.
DriverManager.registerDriver)new OracleDriver());
String url = "jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=TCPS)(HOST=host)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=someName))(SECURITY= (SSL_SERVER_CERT_DN=\"CN=TESTSERVER\")))";
java.util.Properties props = new java.util.Properties();
props.setProperty("javax.net.ssl.keyStoreType", "Windows-MY");
props.setProperty("javax.net.ssl.keyStore", "NONE");
props.setProperty("javax.net.ssl.trustStoreType", "Windows-ROOT");
props.setProperty("javax.net.ssl.trustStore", "NONE");
props.setProperty("oracle.net.ssl_server_dn_match", "true");
props.setProperty("oracle.net.authentication_services", "(TCPS)");
Connection conn = DriverManager.getConnection(url, props);
This code fails with the exception:
java.sql.SQLRecoverableException: IOException: The Network Adapter could not establish the connection
This article should give your more details. Although it doesn't use the system properties, Windows-MY is clearly a store type and it's not file based. Therefore, javax.net.ssl.keyStoreType should be Windows-MY and javax.net.ssl.keyStore should be set to NONE (upper case may matter), see the JSSE Ref Guide (Customization):
javax.net.ssl.keyStore system property
Note that the value NONE may be specified. This setting is appropriate if the keystore is not
file-based (for example, it resides in a hardware token).
You may also need to configure your trust store in a similar way if your server certificate isn't trusted by your default Java trust store.