Client Certificate using Weblogic - java

Background:
I am working on a project that involves the client to authenticate itself (via client certificate). We are trying to launch a third party app which first authenticates the client cert and then launches its app.
We are using Java and SSL hanshake, and our client server is Weblogic 10.x. The client certificate is in PKCS12 format (cannot change this)
This is the piece of code for presenting the certificate:
System.setProperty("javax.net.ssl.keyStore","MyPath/cert.pfx");
System.setProperty("javax.net.ssl.keyStorePassword","MyPwd");
System.setProperty("javax.net.ssl.keyStoreType","PKCS12");
url.openConnection();
Now all this works pretty well from a standalone. The problem starts when we put this on weblogic. Sometimes it works, sometimes 'Client certificate not present' (http 403.7) is returned. I have tried various combinations (including configuring custome keystore on weblogic console) but nothing seems to work. Any idea why would weblogic altogether ignore the SSL settings (it doesnt throw an error even if I set keystore to a non-existent file)? System.setProperty for SSL just appears useless on weblogic!

In Weblogic 12c you also need add the parameter -DUseSunHttpHandler=true in order to tell the weblogic server to use the Sun Http Handlers instead of its own. Therefore you need the following Java VM parameters:
-Djavax.net.ssl.keyStore=MyPath/cert.pfx
-Djavax.net.ssl.keyStoreType=PKCS12
-Djavax.net.ssl.keyStorePassword=MyPwd
-DUseSunHttpHandler=true

Finally found the solution! Weblogic seems to over-ride the keystore configurations if it is done through Java as above. The thing that worked for me was to configure the SSL settings on JVM level, at web-logic start-up.
To make it work, I just added these Java options in the start-script for weblogic:
-Djavax.net.ssl.keyStore=MyPath/cert.pfx
-Djavax.net.ssl.keyStoreType=MyPwd
-Djavax.net.ssl.keyStorePassword=PKCS12
Restarted web-logic and SSL has been working great since then :)

Related

How to use Jetty with Let's Encrypt certificates?

I want to use certificates from Let's Encrypt with a large count of Jetty servers. One of the problems is that the certificates from Let's Encrypt has a lifetime of 90 days.
To handle this the Jetty server or some extra code must renew the certificate frequently.
Can Jetty handle this self? If yes how can I enable this?
If I need to implement it self with a Java client then how can I replace the certificate dynamically via Jetty API without a restart of the Jetty server?
Edit: Some related and partial helpful links:
setting ssl keystore at runtime in Jetty
Changing Jetty SSL server certificate on-the-fly
Since version 9.3.15 you can use:
SslContextFactory.reload(Consumer<SslContextFactory>)
For details see at: https://github.com/eclipse/jetty.project/issues/918

Apache directory API refuses to add user to Active Directory "(UNWILLING_TO_PERFORM)"

Im trying to add a user using Java 6 and Apache Directory API to Active Directory running on windows server 2008, but the result i get is (UNWILLING_TO_PERFORM), now i understand that it needs a secure connection and to use unicodePwd attribute to add the password, which i did, or at least tried to do.
The server admin created a certificate for the account i use when adding users, i exported it and added it to cacert in /jre/lib/security/.
I tried to see if i can just connect securely to the AD server without performing any operations, i get 2 scenarios that fail on the binding operation .bind():
1- if i connect using port 636 and use startTLS() available in ldapNetworkConnection : then i either get PROTOCOL_ERROR server will disconnect
2- if i connect using port 389 and use startTLS() available in LdapConnectionConfig i get "Failed to initialize the SSL context" and "IllegalArgumentException :TLSv1.1"
I added the trust manager but still no luck, below is the code so far.
LdapConnectionConfig config = new LdapConnectionConfig();
config.setLdapHost(IP);
config.setLdapPort(389);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore)null);
config.setTrustManagers(tmf.getTrustManagers());
config.setName("CN=TestAdmin,CN=Users,DC=bmrk,DC=com");
config.setCredentials("P#ssw0rd");
LdapNetworkConnection ldapNetworkConnection = new LdapNetworkConnection(config);
ldapNetworkConnection.connect();
ldapNetworkConnection.startTls();
ldapNetworkConnection.bind();
// EDIT
i switched to JNDI LDAP APIs it gave me a more reasonable error, apparently the issue comes from the SSL handshake, my app isn't able to find the valid certificate, any recommendations?
Any help is really appreciated.
Thanks,
In Case anyone is interested, my only issue was in the adding the server that generated the certificate as a CA authority in the cacerts file so that the JVM can trust certificates issued by the server although it worked smoothly and perfect with JNDI ldap APIs it doesn't work with Apache Directory not sure why.
so my recommendation is to use JNDI instead of Apache Directory and make sure you export the certificate for the account used to login to Active Directory as PKCS12 and add it to the keystore.
so it's 2 certificates, 1 for the login/bind account and 1 for the server to act as a CA (Certificate Authority).
Also Java 6 support TLSv1 as a maximum security protocol which isn't the standard case with Apache LDAP, so either upgrade you Java or use JNDI.
it works perfectly with Java 7.

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.

Jetty require SSL client certificate by URL

I would like to run a servlet in Jetty on an HTTPS site that requires a client certificate for only part of the site (specific URLs). For example:
https://example.com/someservlet/public - no client cert required
https://example.com/someservlet/protected - client cert required
In Apache I can accomplish this by specifying SSLVerifyClient require inside a <Directory> or <Location> which forces Apache to renegotiate the SSL connection after the request is made.
I do not want to run Jetty embedded in anything else, just standalone. Is this possible? Can a Servlet cause this directly somehow? Can it be done via configuration?
As far as I know you can only specify the SSL options on a per-port basis.
Even if you could the configuration you are trying to achieve is problematic, as it needs the SSLRenegotiation which has been changed about a year ago because of a security vulnerability. The new method for performing an SSLRenogitiation is therefore only supported by newer clients and sometimes even if it is supported it does not work because of bugs.
My recommendation for an easy workaround: Configure Jetty to listen on two SSL ports:
For example on 443 without HTTPS Client auth and on 8443 with HTTPS client auth required. Then make your protected servlet only available on 8443. This is not a nice solution but 100% robust, works with Jetty and with all clients.

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