Tuesday 18 June 2013

Creating JBOSS Enterprise Data Services with WS-Security secured SOAP Web Services

This posting provides a concise set of technical notes on how to consume a WS Security secured SOAP Web Service with JBOSS Enterprise Data Service 5.3.1.

Steps


  1. Create a SOAP Web Service Data Source Connection and Generate Source & View Models
  2. Create a custom Password Callback Handler.
  3. Setup the CXF Web Services configuration. 
  4. Create a JBOSS Data Source for the SOAP Web Service Data Source Connection.
  5. Publish as the new Data Service View Model as a Virtual Database.
  6. Query the new Data Service using a JDBC SQL Client.


Preparation

The following tools were used in this exercise:

  • JBOSS Enterprise Data Services 5.3.1 (Embedded in the JBOSS SOA-P platform) – aka “JBOSS-EDS”
  • JBOSS Developer Studio 5.0 (includes the TEIID Perspective) – aka “JBDS”
  • Squirrel SQL (JDBC SQL Client)
  • A WS-Security secured SOAP based Web Service using the following WS Policy:  Wssp1.2-2007-Https-UsernameToken-Plain


It is assumed that the reader has developed Web Service backed Data Service using JBOSS EDS and that their environment has been installed and configured appropriately.

Objective

The goal of this document is to describe how to consume a WS Security secured SOAP based Web Service with JBOSS EDS and build a Read Only Data Service on top of it.  For those who are not familiar with WS Security, please review this document for an overview: 

http://en.wikipedia.org/wiki/WS-Security .  

This type of solution is required in a few Use Cases such as:

  • A set of WS Security secured SOAP Web Services present an access point to Data which is needed for a Federated Data Service (that is we wish to merge it with data from another Data Source such as a Relational Database).
  • A set of WS Security secured SOAP Web Services present an access point to Data which is in a proprietary format and we wish to introduce a Canonical model to provide consistent formatting and dictionary across the Enterprise.

Please note that this mini-guide is not exhaustive, but aims to cover off some of the less obvious aspects of creating a JBOSS EDS Data Service for a WS Security secured SOAP Service.  Many aspects of this process are already covered in the Red Hat documentation Guide for JBOSS EDS 5.3.1 : 

https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Data_Services/5/html-single/Teiid_Designer_User_Guide/index.html.

Now onto the details…

Step #1: Create a SOAP Web Service Data Source Connection and Generate Source & View Models

In the JBOSS EDS 5.31 / JBDS 5.0 release of the product there is no support in the GUI to create a Web Service Data Source that has WS Security in place (only support for no security or HTTP Basic).  




The work around for this is to create a connection using the “None” Security Type.  

Once created, use the “import” feature on the JBDS menu from your project to import a SOAP Web Service for Source and View Models.

With the Source and View Models created, be sure to use the connection that was earlier prepared.  

Hint:  Make sure that the URL from the SOAP WSDL is in alignment with the Host certificate if the SOAP URL uses HTTPS.  This can be done by opening the Source Model of the SOAP Service using an XML Editor and updating the PORT reference to use a Fully Qualified Domain Name that lines up with the SSL Cert that the host has installed ( it is in a configuration called key="connection:EndPoint").

Step #2: Create a customer Password Callback Handler

In order to handle the “credential” (password) side of the authentication with a WS Security policy that implements a Username Toke scheme, one common approach is to provide a password.  The password in this example is a static string that is stored in a Java Class.  This is by no means a best practice and should not be considered final for a Production Deployment.  More realistic options would include re-implementing the provided class to better secure the password at rest.  The following source was provided by the JBOSS EDS team as an example only:


UsernamePasswordCallback.java

package org.teiid.soap.wsse;

import java.io.IOException;


import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class UsernamePasswordCallback implements CallbackHandler {


/*

* This class should be updated to use implementation specific
* authentication. it is not recommended to use for production as-is.

* @see
* javax.security.auth.callback.CallbackHandler#handle(javax.security.auth
* .callback.Callback[])
*/
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {

for (int i = 0; i < callbacks.length; i++) {

if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
if ("myUsername".equals(pc
.getIdentifier())) {
pc.setPassword("user01");
}

} else {

throw new UnsupportedCallbackException(callbacks[i],
"unrecognized_callback"); //$NON-NLS-1$
}
}

}

}
  

Step #3: Setup the CXF Web Services configuration

This is the least well documented step.  In the JBOSS SOA-P installation, find the “Active Deployment” that you are using.  For example, the setup used for this mini-guide is as follows:

C:\software\jboss-soa-p-5\jboss-as\server\default

Below this directory there are 2 relevant sub-directories: 
deploy – where all the WAR files, Data Source Files (*-ds.xml), EAR files and other deployments go
conf – where some key configuration files are kept
Inside the conf sub-directory create an XML file with the following settings:

WS-ABC-CONFIG.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="http://cxf.apache.org/transports/http/configuration
                           http://cxf.apache.org/schemas/configuration/http-conf.xsd
                           http://www.springframework.org/schema/beans
                             http://www.springframework.org/schema/beans/spring-beans.xsd
                             http://cxf.apache.org/jaxws
          http://cxf.apache.org/schemas/jaxws.xsd">


<jaxws:client name="{http://teiid.org}SOAP-SERVICE-ABC"

createdFromAPI="true">

<jaxws:outInterceptors>
<ref bean="Timestamp_Request" />
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor" />
</jaxws:outInterceptors>

<jaxws:features>

<bean class="org.apache.cxf.feature.LoggingFeature" />
</jaxws:features>
</jaxws:client>

<bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor"

id="Timestamp_Request">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken" />
<entry key="passwordType" value="PasswordText" />
<entry key="user" value="myUsername" />
<entry key="passwordCallbackRef" value-ref="myPasswordCallback" />
</map>
</constructor-arg>
</bean>

<bean id="myPasswordCallback" class="org.teiid.soap.wsse.UsernamePasswordCallback" />


<http-conf:conduit name="*.http-conduit"

xmlns:sec="http://cxf.apache.org/configuration/security" xmlns="http://cxf.apache.org/transports/http/configuration">
<http-conf:tlsClientParameters
disableCNCheck="true" useHttpsURLConnectionDefaultHostnameVerifier="false" />
</http-conf:conduit>

</beans>



The key items to configure for your environment include the following:

  • bean class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor" – set the SOAP Username here under the ‘user’ key; Also set the reference to the Password callback class here under the ‘passwordCallbackRef’ key. 
  • disableCNCheck – set this up if you are having challenges with HTTPS and certificates on Pre-PRODUCTION environments.


Step #4: Create a JBOSS Data Source for the SOAP Web Service Data Source Connection
Next create a JBOSS Application Server data service for the SOAP Web Service.  This config goes in the active deployment ‘deploy’ sub-directory.  This is where the CXF config file is referenced to ensure that the security is configured.

MyDataSource-ds.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<connection-factories>
    <no-tx-connection-factory>
        <jndi-name>MyDataSource</jndi-name>
        <rar-name>teiid-connector-ws.rar</rar-name>
        <use-java-context>true</use-java-context>
        <connection-definition>javax.resource.cci.ConnectionFactory</connection-definition>
        <jmx-invoker-name>jboss:service=invoker,type=jrmp</jmx-invoker-name>
        <min-pool-size>0</min-pool-size>
        <max-pool-size>10</max-pool-size>
        <blocking-timeout-millis>3000</blocking-timeout-millis>
        <idle-timeout-minutes>31</idle-timeout-minutes>
        <prefill>false</prefill>
        <background-validation>false</background-validation>
        <background-validation-millis>0</background-validation-millis>
        <validate-on-match>true</validate-on-match>
        <use-fast-fail>false</use-fast-fail>
        <statistics-formatter>org.jboss.resource.statistic.pool.JBossDefaultSubPoolStatisticFormatter</statistics-formatter>
        <isSameRM-override-value>false</isSameRM-override-value>
        <allocation-retry>0</allocation-retry>
        <allocation-retry-wait-millis>5000</allocation-retry-wait-millis>
        <config-property type="java.lang.String" name="EndPoint">https://VM-EAP-DS-DEV01:8002/ItemMaster_v4-context-root/ItemMasterImplPort</config-property>
        <config-property type="java.lang.String" name="SecurityType">WSSecurity</config-property>
        <config-property type="java.lang.String" name="template-name">connector-ws</config-property>
        <config-property name="ConfigFile">${jboss.server.home.dir}/conf/WS-ABC-CONFIG.xml</config-property>
        <config-property type="java.lang.String" name="ConfigName">JDE-World-SE</config-property>
    </no-tx-connection-factory>
</connection-factories>

The properties that are important to configure here include:

  • JNDI Name – this goes into the JBOSS AS runtime and is how the JBOSS EDS Virtual Database refers to the underlying SOAP connection.  Since this is generated to some degree, you may have to take what the VDB Editor shows and use it to over-ride the value in this property.
  • End Point – ensure this is the correct URL using the same name as the SSL Certificate and your corporate DNS server.  If the WSDL uses internally IPs (i.e. 192.168.1.x or 127.0.0.1) there might be challenges depending on deployment configurations into Production.
  • ConfigFile – this is the reference to the CXF xml config file we looked at in step 4 above.  This is an absolute path to the file.


Step #5: Publish as the new Data Service View Model as a Virtual Database

The next step is to create a new Virtual Database in the JBDS tool with the Teiid Perspective.  Add in the Source and View Models.  Check that the JNDI name which references the Data Source which was configured in Step 5 is correct.  If not, just edit the value in the Data Source (*-ds.xml) file since the VDB does not allow this to be changed.

Step #6: Query the new Data Service using a JDBC SQL Client

Finally, deploy the VDB to the JBOSS EDS runtime and test the new Data Service with a standalone JDBC SQL Client.  Squirrel SQL provides one option for this task.  Add the Teiid-client.jar as the JDBC driver, and add a new Alias for the connection:
Example JDBC Alias for a Teiid VDB

jdbc:teiid:MyVDB@mm://localhost:31000;ApplicationName=squirrelSqlDmh

Once connected, try the Data Service with a SQL Query.  An example query can be generated from the JBDS “Scrapbook” View.  A sample might look something like:

select * from (exec "MySoapServiceView"."getSomething"('aParameter')) as X_X

And that concludes this mini-guide.  Much of the related work is well documented in the product documentation which can be found at the start of this document.
It is recommended that a new Teiid Developer work through an end to end example with an unsecured SOAP Web Service prior to trying to consume a WS Security secured Web Service.

For and questions or suggestions please post to this blog.

1 comment: