Add client certificate for outgoing OSB call

Simple use case……you want to connect to a customer system over the internet. The customers system has an API but requires 2-way SSL. This means we have to send a client certificate along to make sure the SSL handshake can be completed. If your server has already a server certificate installed, it will send this one along by default but the customers system won’t accept it as it is different then what it trusts. In the next section, I will explain how to add a client certificate to an outgoing OSB call.

SSL

Let’s say I want to connect to my favourite climbing shop www.mountaingear.com as they have a nice backend api to take orders. The guys from mountaingear.com created a certificate for me to send along with the call.

First I am going to generate a keystore with a private key in it, to simulate the certificate which the third party gave to me.

keytool -genkey -keyalg RSA -alias climber -keystore keystore.jks -storepass password -validity 360 -keysize 2048

If I open the created JKS using keystore explorer I see a keypair we just created.

MyCertificate

Copy the jks to my OracleHome say ORACLE_HOME/keystores.

The next thing we have to do is to create an PrivateKeyInfrastructure Provider. Go to weblogic console and then:

  • Security Realms
  • myrealm
  • Providers
  • Credential Mapping
  • New –> Set your name here. Mine is MountainGearPKIProvider. Set the type to PKICredentialMapper. Click OK to finish.

PKIProvider

Restart the Admin server for the changes to take effect.

When the admin server has restarted we are going to configure the PrivateKeyInfrastructure Provider we just created. Go to weblogic console and then:

  • Security Realms
  • myrealm
  • Providers
  • Credential Mapping
  • MountainGearPKIProvider
  • Provider Specific –> KeystoreType = JKS, Keystore File Name = The location of your just created jks…mine is G:\Oracle\Middleware\OracleHome\keystore\MountainGear.jks, KeyStorePassphrase = password, Confirm KeyStorePassphrase = password. Click Save to finish
    • PKIProviderConfiguration

      Restart the Admin server again for the changes to take effect.

      After this, go to the SBConsole and start a new session. In a project, create a folder which will hold the ServiceKeyProvider. Mine will be in my Accounts project. Create a ServiceKeyProvider in this new folder and select using SSL Client Authentication the right certificate. Set the password, save it and activate it.

      ServiceKeyProvider

      The reason why we do this in the OSB console is that it cannot resolve the PKIProvider in JDeveloper. The only work around is to create it on the server and then export your project and import it into JDev. After you have done this, you can see your ServiceKeyProvider.

      The last step now is to make sure it is send along with a flow. The only thing we have to do, to accomplish this is to select the proxy service and go to the Security tab. Here you can select the Service Key Provider.

      ProxyService

Checking SSL connection using Java

Sometimes SSL issues are the worst there are. Unreadable logging, strange codes and other unprehencible messages. There is a simple way to check if your 1-way SSL is being setup correctly using Java. Here is how it works:

The first thing we have to do is to write a class which makes a simple HTTP request to a HTTPS url. This would look something like this:

package nl.redrock;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
 
import junit.framework.TestCase;
 
import org.junit.Test;
 
public class SSLTest extends TestCase {
 
    @Test
    public void testSSL() throws Exception {
 
        // https://someserver.net:999/someservice?wsdl
        URL verisign = new URL("http://myserver.nl:8888/service/hello?WSDL");
 
        System.out.println("Opening URL: " + verisign.toString());
 
        BufferedReader in = new BufferedReader(new InputStreamReader(
                verisign.openStream()));
 
        String inputLine;
 
        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);
 
        in.close();
    }
}

This class just prints to system out all the input received from the url. We made it a testcase so we are able to run it using JUnit. We can run the testcase when we run it using mvn:test as we are again using our favourite tool Maven. This will result into some PKIX error….it looks like this:

Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

This is probably because the certificate of the server you are connecting to, isn’t trusted by the client. How do we fix this?
We add the server certificates to the cacerts of the JDK we are using to run the client or you can use the truststore of the client you want to mimic. You can configure this in your pom like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>nl.redrock</groupId>
    <artifactId>HelloService</artifactId>
    <version>1.0</version>
     
    <properties>
        <java.version>1.5</java.version>
    </properties>
     
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <type>jar</type>
            <scope>test</scope>
        </dependency>
    </dependencies>
     
    <build>
        <plugins>
            <!-- plugin for setting the compiler version -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <!-- Plugin for setting properties for the tests to run -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <systemProperties>
                        <property>
                            <name>javax.net.ssl.trustStore</name>
                            <value>keystore.jks}</value>
                        </property>
                        <property>
                            <name>javax.net.ssl.trustStorePassword</name>
                            <value>MYPWD</value>
                        </property>
                        <property>
                            <name>ssl.debug</name>
                            <value>true</value>
                        </property>
                        <property>
                            <name>weblogic.StdoutDebugEnabled</name>
                            <value>true</value>
                        </property>
                        <property>
                            <name>javax.net.debug</name>
                            <value>ssl,handshake,verbose</value>
                        </property>
                        <property>
                            <name>javax.net.ssl.keyStore</name>
                            <value>keystore.jks</value>
                        </property>
                        <property>
                            <name>javax.net.ssl.keyStorePassword</name>
                            <value>MYPWD/value>
                        </property>
                    </systemProperties>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Now when you run mvn:test your should get a nice overview of the whole SSL handshake and certificates.

Using JDeveloper to deploy to weblogic over SSL

When you start working with the SOA Suite 11G the server has a default keystore set. Connecting to this setup over HTTPS usually doesn’t give any problem as the CA’s used are generally trusted by default by the JDK used. One of the things you maybe are going to encounter when you equip your server with a genuin certificate with CA’s in the chain which are not trusted by default, is that the deployment using JDeveloper is not going to work anymore. This is because the SSL handshake will cause an error as JDeveloper doesn’t trust the server. How to solve this……
Continue reading

Unable to access external HTTPS endpoint in BPEL 11g

We where trying to connect from BPEL to a HTTPS service but we ran into SSL problems. After checking all the keystores and it’s locations, it still didn’t seem to pick our keystore up.

The error we found in the log looked like this:

Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Continue reading