Tuesday, March 19, 2013

Using Secure Web Services HTTPs (SSL)



Ever have trouble using SSL to call web services... using https can cause a challenge now and then to using web services. Here's some of the different problems I've run into over the years and the way I got around them...

Here are some of the errors I've seen...

When using an Axis2 :


org.apache.axis2.AxisFault: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.apache.axis2.AxisFault.makeFault(AxisFault.java:417)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:72)
at ...

org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:327)


at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:206)

... 35 more

... 53 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 58 more

Or this:

AxisFault:Unconnected sockets not implemented 

When using IBM Websphere with JAX-WS you may see this:

WSWS7130E: No Secure Sockets Layer (SSL) configuration is available for the https:…

These errors are due to the fact that the java runtime environment cannot find the certificate that says you are allowed to talk to this server. So, it doesn't "trust" this provider and will complain loudly and differently depending on the web service framework you are using... 

Regardless of the framework, in order be able to use https, you have to add the providers certificate to your truststore to let you JRE know that you are allowed to talk to this service provider. Each JDK/JRE has it's default trust store called cacerts... you should copy this to create your own truststore and then add/import your certificates to it.

How to get the certificate of the service provider…


Using Microsoft Internet Explorer:

1) Point your web browser at the https address the client gave you.
2) You should see the warning box "Security Alert"
3) Click on the "View Certificate" button.
4) Click on "Install Certificate"
5) Then click on "Tools/Internet Options.
6) Select "content" tab.
7) Click Certificates.
8) The click the "Other People" tab.
9) Export it to your local machine.



Using Google Chrome:
1) Point your web browser at the https address the client gave you.
2) Click on the little lock icon beside the address :
3) Then click Certificate Information and goto the Details tab:




4) Then click Copy to File… During the wizard, save it as a DER file.



Importing your certificate into the truststore


Once you have your certificate (however you get it) then you can import it into your truststore.


Standard JRE import
Here's how to import a certificate into a standard JRE(note this shows modifying the original cacerts which may be ok for local development)... find the keytool under the bin folder...


C:\Program Files\Java\jre1.5.0_12\bin\keytool

use this command:

keytool -keystore "C:\Program Files\Java\jre1.5.0_12\lib\security\cacerts" -import -alias myTrustedServer -file C:\dp.cer -trustcacerts

EXAMPLE:


C:\Program Files\Java\jre1.5.0_12\bin>keytool -keystore "C:\Program Files\Java\jre1.5.0_12\lib\security\cacerts" -import -alias myTrustedServer -file C:\dp.cer -trustcacerts
Enter keystore password:  changeit
Owner: CN=*.new.net, OU=Enterprise, O=My Co Insurance, L=Columbus, ST=Ohio, C=US
Issuer: CN=*.new.net, OU=Enterprise, O=My Co Insurance, L=Columbus, ST=Ohio, C=US
Serial number: 6d4bb402
Valid from: Mon Jul 30 09:36:08 EDT 2007 until: Thu Jul 27 09:36:08 EDT 2017
Certificate fingerprints:
        MD5:  <bunch of numbers and letters>
        SHA1: <bunch of numbers and letters>
Trust this certificate? [no]:  yes
Certificate was added to keystore



import into IBM RAD jdk:

To import the cert into RAD's “default jdk”:


C:\Program Files\IBM\SDP80\jdk\bin>keytool -import -v -trustcacerts -alias MyAlias -file C:\dp.cer -keystore "C:\Program Files\IBM\SDP80\jdk\jre\lib\security\cacerts"


The default password for the keystore is "changeit"  (took me some googling to get that :)

NOTE for JUnit tests: If using JUnit tests to call web services, I'd recommend that you use the default JDK for the JRE instead of one of the Websphere Server JREs.  There seems to be issues getting SSL to work no matter what I’d tried when running JUnit tests using the Websphere JRE.  Switching to the default JDK for RAD as your JRE for running the JUnit’s allow SSL to work just fine if you add the certificate as outlined directly above.



Import cert into Websphere Application Server V6.x and higher

In WAS Admin Console  
Click on
Security -> SSL certificate and key management -> Key stores and certificates -> NodeDefaultTrustStore - > Signer certificates


Click on Add to add a new certificate.


Alias : <any name> i.e. myCert
File Name : <<fully qualified certificate File name i.e. C:/dp.cer>>
Data Type : Base64-encoded ASCII data


Hit Apply & OK to save the changes.


Restart the WAS server.


To use your custom truststore 

If you actually modify the cacerts file, the jre will find the certs with no extra work.  To use your own custom keystore use the following command line arguments when starting the JVM:

-Djavax.net.ssl.trustStore=C:\temp\myTrustStore -Djavax.net.ssl.trustStorePassword=changeit




Issue with Using IBM's JAX-WS runtime:

We ran into an issue once trying to call web services from a batch job while using IBM's JAX-WS implementation.... We would get this error:


WSWS7130E: No Secure Sockets Layer (SSL) configuration is available for the https:…


We discovered we had to create a truststore of a specific type and use it. To do this we created a new "Key database" using iKeyman. How to find iKeyMan click here.

To fix our issue we used ikeyman to create keystore/truststore using PKCS12 type. ( https://www-304.ibm.com/support/docview.wss?uid=swg21303472 )




I had to enter a password and couldn’t get around it.


Once you create the keystore, add the certificate to it by clicking Add….



Import the cert and click OK.


Close iKeyMan.


Now when you run your JAX-WS client add the following arguments to the JVM…


-Djavax.net.ssl.trustStore=C:\temp\sso.p12 -Djavax.net.ssl.trustStorePassword=changeit


Of course use your keystore location and password., but after this you should be good to go.


Hope some of this information helps!


1 comment:

  1. Reading this article was crucial for getting an application back online after it was refusing the SSL handshake due to a changed server certificate.. Thanks a lot!

    ReplyDelete