Web Services, SSL, and self-signed server certificates
This question has come up again recently by a customer and I thought I'd post about it again. The customer downloaded the SDK, compiled the java sample applications, and tried to run them against one of their BIG-IPs. To their surprise the following error was presented: No trusted certificate was found.
Now is when I need to step back a bit and talk about SSL trust. You all have probably seen the warning message that occasionally pops up when browsing to a website encrypted with SSL. This is due to the fact that one of the following conditions in the certificate is not valid:
- The certificate is not signed by a trusted certificate authority (CA)
- The certificate date is invalid (expired, etc.)
- The name embedded in the certificate does not match the hostname in the URL used to access the site
If any of these conditions are met, then the browser will "warn" the user that something may be amiss and that they should proceed with caution. Well, the same security mechanisms are in place in the various networking libraries in the java and .NET runtimes. During the SSL negotiation process, if the server certificate isn't found to pass all the security criteria, then, by default, the connection will not be allowed.
In general, most of our customers don't get their BIG-IP certificates signed by a CA, but rely on the default self-signed certificate created by the system. This is a no-no for policy issue #1 above.
The .NET platform provides a way to override the default certificate policy via the System.Net.ServicePointManager.CertificatePolicy. You can easily whip up your own override and tell the underlying runtime to use your policy instead. Whalah, problem solved. You can check out this article I wrote on the .NET solution: Configuring .NET SSL Security in a Trusted Environment
But for java, it's a bit trickier. I have yet to find a way at runtime to override the policy section of the SSL core routines. Also, Apache WS-SOAP and Apache Axis do things a bit differently under the seams so a common solution for all java platforms seems not possible. If anyone out there knows how to do this, PLEASE let me know. I'll throw some F5 goodies your way if I get something working that I can include in the SDK.
With the java toolkits, you must install take steps on the client side to make security policy #1 true. To do this, you must install the server certificate in the local truststore which basically tells the client runtime that the server is a "trusted" source. How do you do this you ask? Well, there are several ways.
1. The brute force approach.
A while back I wrote a article discribing how to manually install the certificate in your client truststore by security copying (scp) it from the BIG-IP to your client machine, and then using the jdk's keytool command to import it into the truststore. This article can be found here: Configuring SSL Communications with Apache SOAP
2. The "somewhat" automated approach.
I got to thinking that there has to be a programmatic access to the certificate when initiating a SSL connection and I knew there were classes that could be used to access the truststore, so I went to writing a little client side utility to do the grunt work for option 1. I introduced installCert.java into the 4.6.2 version of the iControl SDK. This is now available in the Code Share section on DevCentral, as well as in the 4.6.2 and 9.0 versions of the iControl SDK. Do a Search in the DevCentral forums for installCert and you'll find some topics related to it's usage.
Hopefully this clears things up a bit for everyone. Again, if anyone has a solution to the runtime override of the java security policy with Apache WS-SOAP and Axis, PLEASE let me know. I'm very interested!!!
-Joe
- Frank, thanks for the pointer. I haven't posted this solution to my blog (I guess I should). A DevCentral user uploaded a sample class to our CodeShare section that will hook itself into the stack without a rebuild of the 3rd party library (I've tested with axis and WSSOAP). Check out the XTrust JSSE Provider sample over in CodeShare. Your calling application needs only the following line:
 
 
XTrustProvider.install(); 
 
Pretty slick... 
 
-Joe - I don't have much experience with publishing web services with JBuilder.
- The CodeShare link has been fixed in the post and the XTrustProvider.java source file has been added to the CodeShare with the topic: JavaTrustProvider.