Tuesday 6 November 2007

How to set up an SSL test environment with OC4J and Oracle BPEL

Recently, I needed to configure a SSL test environment configured with a self-signed certificate, a Oracle BPEL process for the SSL client and a EJB3 HelloWorld service secured with SSL. As an Oracle employee the choice for a (standalone) OC4J as the server container should be evident.

This post is hopefully a step by step tutorial to configure this SSL test environment.

OC4J container
- Download and install a standalone OC4J container version 10.1.3.3 from OTN

Developing a HelloWord EJB3 service
- Use the EJB3 session bean wizard in JDeveloper 10.1.3.x to generate the skeleton code for you HelloWorld service. Make sure that you also generate a webservice interface.
- Add a simple HelloWorld method to your bean implemention and add this method signature to the webservice interface as well. The method will now be exposed as a webservice operation when
deployed to the OC4J container.
- Add JSR-181 annotation to webservice interface to configure the webservice wsdl. Here's an example that I used:


package nl.oracle.com.ssl;

import java.rmi.Remote;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

import oracle.webservices.annotations.Deployment;


@WebService(name="HelloWorldWS",
targetNamespace="http://ejb.oracle.com/targetNamespace",
serviceName="HelloWorldWSService")
@Deployment(contextPath="ejb-ws",
uriPath="HelloWorldWS",
portName="HelloWorldService")

public interface HelloWorldEJBWebService extends Remote {

@WebMethod
public void helloWorld(@WebParam(name="input") String in);
}

After finishing the implementation cycle you generate a deployement descriptor and deploy it to your just installed OC4J container. Verify that you can access the webservice and test it with the Test Webservice functionality.

Configure OC4J for SSL
(look here for more info)

First, we need to generate a self-signed certificate and put it in a new keystore. Use the keytool utility from java SDK.
Generate a certificate using the following commando:

keytool -genkey -alias oc4j-server -keyalg RSA -keypass welcome -storepass welcome -keystore c:\oc4jserver.jks

You will be prompted for specific certificate information. YOU HAVE TO MAKE SURE THAT THE "FIRSTNAME/LASTNAME" question is answered with the hostname of the server on which you have installed the OC4J container (I used localhost, because the container is running on my laptop). This will overcome "wrong hostname" exceptions later on.

Now you have a RSA encrypted certificate in the oc4jserver.jks keystore located in the root of your C drive.

As a second step, we need to configure which web application we want to secure with SSL. Open the $ORACLE_HOME/j2ee/home/config/default-web-site.xml file
and copy all the contents to $ORACLE_HOME/j2ee/home/config/secure-web-site.xml (create the file when it does not exist yet). Change the element and make
sure that it looks like the example below. Change where needed.

<web-site xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/web-site-10_0.xsd"
port="4443"
secure="true"
display-name="OC4J 10g (10.1.3) Default Web Site"
schema-major-version="10"
schema-minor-version="0" >
...
<ssl-config keystore="c:\oc4jserver.jks" keystore-password="welcome" />
...
</web-site>

Delete all the web-app entries except the helloworld entry and the default web application entry. Here is the one that I am using:

<?xml version="1.0"?>

<web-site xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/web-site-10_0.xsd"
port="4443" secure="true" display-name="OC4J 10g (10.1.3) Default Web Site" schema-major-version="10" schema-minor-version="0" >
<default-web-app application="default" name="defaultWebApp" />
<web-app application="helloworld" name="helloworld" load-on-startup="true" root="/ejb-ws" />
<access-log path="../log/default-web-access.log" split="day" />
<ssl-config factory="com.evermind.ssl.JSSESSLServerSocketFactory" keystore="d:/java-keystores/mykeystore.jks" keystore-password="welcome" truststore-password=""/>
</web-site>

As a final step we need to tell the OC4J instance that we have some SSL secured web applications add the following line to the server.xml (located under: $ORACLE_HOME/j2ee/home/config/):

<web-site path="./secure-web-site.xml" />

Basically, we now have specified that the OC4J container should secure the HelloWorld webservice with SSL and using the certificate in the specified keystore. You can test this by going to the HTTPS url of the HelloWorld test service (change http to https and change the port to 4443 of the URL you used before).

Configuring JDeveloper and BPEL for the SSL HelloWorld service
To be able to invoke the HelloWorld service over HTTPS we need to make sure that JDeveloper and the BPEL container trust the certificate. I assume that you have installed JDeveloper 10.1.3.x and a BPEL container (I have used a complete SOA Suite installation).

First we have to export the certificate from the oc4j keystore:

keytool -keystore c:\oc4jserver.jks -export -alias oc4jserver-server -file c:\oc4jserver.cer

Now we have a trusted certificate oc4jserver.cer that need to import in the keystore of JDeveloper and BPEL. The command examples will use the standard Java SDK keystore cacerts and
the default keystore password changeit:

keytool -keystore <JDEV_HOME>\jdk\jre\lib\security\cacerts -import -file c:\oc4jserver.cer

Do the same for your BPEL installation.

The SSL configuration is finished now. I leave the implementation of the BPEL process that invokes the HelloWorld service over HTTPS as an exercise for the reader :)