How to specify a local custom SSL truststore for JTOpen? - java

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?

Related

Provide SSL certificate to SQL Server via JDBC

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.

SSL connection error when connecting to MySQL, using JDBC

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.

Mule ESB does not accept SSL cert when deployed on server, but works fine on local dev machine

I have Mule ESB deployed to a Linux server and Anypoint Studio running in my local windows dev environment. I have a fairly simple flow that includes a SalesForce connector. Salesforce REST API has a valid cert signed by VeriSign and my local instance of Mule happily accepts it and connects with no problems. However, when Mule runs on the server it always throws "PKIX path building failed, unable to find valid certification path to requested target".
I've tried using the default java keystore, specifying a keystore with javax.net.ssl.keystore, nothing works.
On my local machine I've ended up doing the following to show that Mule is using the right trust store:
I generated an empty truststore and added it to my AnyPoint project as a resource. I created an HTTPS connector configuration in order to explicitly specify the truststore I want to be used for my SalesForce connector, and pointed it to my empty truststore. When I try to run the project locally, I get the exact same SSL error (as I would expect, since it's an empty truststore). I then take the VeriSign CA cert and add it to my empty truststore. After that, locally everything works just fine. To me, this confirms that my mule project is using the truststore that I've added as a resource to the project itself.
I then export this project and deploy it to my server. On the server it throws the SSL error.
Can there be some weird JVM config differences that could cause this?
It turns out that Mule does not use a different trust store for each service. If you have multiple services deployed to it, the last service to declare a trust store explicitly will force all other services to use that same trust store, overwriting whatever configuration they may have. This was happening in my case. I found this out by echoing out System.getProperty("javax.net.ssl.trustStore"); to log and realized it's a trust store that was a resource in some completely different deployed project but being used by mine.
Seems like a pretty bad screw up by the Mule guys.
I agree with your suspicion that the JDK on your linux server doesn't trust the proper certificates. However, this doesn't need to stop your application from doing so.
I've been able to make the salesforce connector trust a given certificate by doing the following:
KeyStore truststore = KeyStore.getInstance("JKS");
truststore.load(myKeystoreInputStream, myKeystorePassword.toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(truststore);
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, tmf.getTrustManagers(), null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
The key is the last line. The salesforce connector uses HttpsURLConnection directly to connect to the server, while the HTTPS connector doesn't. This will allow your mule application to use a different trust store for salesforce than it uses for one or more HTTPS connectors. You can use this to control the SSL certificates that your application will trust, independently from the certificates that the server's JVM trusts.

How to use the Windows Keystore (MCS) with JDBC?

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.

Mirth: calling an SSL SOAP web service with a client certificate

The scenario is around calling an external SSL SOAP web service from within Mirth. The web service is requires an SSL/TLS connection along with a client certificate.
The intention is to use the built-in SOAP Sender Destination to call the remote secure web service, and somehow include that client certificate.
I understand that you first need to install that client certificate into the Java runtime. This may be within the Java runtime's certificate store or the Jetty certstore.
The platform:
Windows 2003 SP2
Mirth 1.8
Java jre1.5.0_09
Question: what configuration steps (Mirth, JRE certificate stores, etc.) would you suggest to successfully have a Mirth SOAP Sender include a client certificate (*.cer) when calling a web service secured by SSL?
The Java runtime, or more specifically, the Sun JSSE provider, will present a client certificate if some system properties are set. You can read details in the JSSE Reference Guide, but the important properties are javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword.
There are a few drawbacks to this approach. First, setting the key store password as a system property makes it accessible to any code running in that process—although this can be controlled if a SecurityManager is installed. Second, these settings will be used for any SSL sockets created through the "default" SSLContext. If you need different credentials for different endpoints, you'll need a Mirth-specific solution.
No starting point was specified in the question, but if starting from scratch, the easiest approach is to create a new Java Key Store ("JKS" format) and generate a new key pair and a CSR. After sending the CSR to the CA and getting a certificate back, import it into the same key store. That key store is ready to use.
If a certificate is already available, it is likely to be in a stored with its corresponding private key in PKCS #12 format (.p12 or .pfx file). These can be used directly by a Java application, but the javax.net.ssl.keyStoreType property will need to be set to "PKCS12"
Mirth 1.8 cannot send a client cert when calling a SOAP web service.
I'm late a bit here for this but actually there is a possibility that it could. By sending a few config parameters to the JVM you could get the underlying SOAP engine to switch to HTTPs and provide the proper certificate.
refer to this question for details on which parameters to set for configuring the VM
Java HTTPS client certificate authentication
you will notice there are quite a few things to take care of. Normally HTTPs and client authentication should "just work" once you configured your certificates appropriately. BUT there are some servers out there that are not so friendly to B2B style clients so you have to watch out.
Using JDK 6_21 and a few tweaks with the certificate I was able to get one of them servers to behave but it was long and painful on our side for something that takes about 15 minutes to configure properly on the server.
here is another question that address this very issue (client side authentication towards unfriendly servers).
Client SSL authentication causing 403.7 error from IIS

Categories