Saturday, October 12, 2013

How to manage WSDL binding on ESB proxy services



In WSO2 ESB if you associate a backend WSDL file when creating a proxy service it will generate an identical WSDL for the proxy service except WSDL port address's location attribute. Value of the WSDL port address's location attribute is modified according to ESB host name. By default ESB generate WSDL for proxy services with following three bindings.
  1. SOAP 1.1 Binding
  2. SOAP 1.2  Binding
  3. HTTP Binding

But there are some situations that backend service only support one or two of above bindings not all three, specially most of the JAX-WS implementations such as CXF only generate SOAP 1.1 binding.  In such case if you send a message to un-supported binding through the ESB you will  get an error. To avoid such situations you could use following ESB parameters to control WSDL generation.

  <parameter name="disableSOAP11">true</parameter>  
This will avoid generation of SOAP 1.1 binding

   <parameter name="disableSOAP12">true</parameter>  
This will avoid generation of SOAP 1.2 binding

 <parameter name="disableREST">true</parameter>   
This will avoid generation of SOAP 1.2 binding



Please note above setting can be used with Apache Synapse  as well.

Sunday, August 04, 2013

WSO2 ESB proxy services for JAX-WS backends


Proxy service concept is one of the main useful component in WSO2 ESB.  There are number of variant formats available to create proxy services such as pass-through proxy , WSDL based proxy, security proxy etc.  When creating a proxy service it is possible to assign a WSDL file to describe the service this simplify service invocation from client side, usually client side tools are capable of understanding WSDL file associate with the proxy service so that they can generate client codes or can generate expected sample messages . As an example once the WSDL given SoapUI can generate expected sample messages.  When a message is reach to the ESB and if it dispatch to a WSDL based proxy service then it's required to dispatch the message to a operation within the service in order to redirect messages  to backend service, in this case dispatching to the service level only (without dispatching to a operation ) is not sufficient.  But if you don't associate WSDL file during the proxy service creation then to redirect message to the backend service-level dispatching is sufficient.

In users point of view there are some use cases that operation level dispatching is useful.

1.  Apply QoS features such as throttling, security per operation level instead of service level.

2. Associate WS-Policy per operation instead of per service.


Both service and operation dispatchers use information available with incoming messages to find correct service/operation, those information can be transport level properties or message level properties some of the given below.

  1. Request URI
  2. SOAPAction HTTP header 
  3. WS-Addressing headers
  4. QName of the first child under SOAP Body element. 
Here first it try to dispatch messages based on transport level properties and if it fails it try to perform dispatching based on message properties such as QName of the root element. Please note if it's possible to complete dispatching only based on transport level details that improves  overall performance of the invocation because there is no need to build the message to find dispatching information. But in practical situations due to various reasons it is not possible to complete dispatching only using transport level details once such common use case is described below.


Use case -1

In JAX-WS specification it's not mandatory to generate unique SOAPAction property per each operation unless developer specifically annotate the SOAPAction with SEI, by default for JAX-WS services it generate "" as the expected value for all operation. Assume you create a WSDL associated proxy service for JAX-WS service and client send following data to the proxy service.
  • Valid SOAP message
  • Request URI up to service level ( e.h http://host/proxyServiceName )
  • HTTP SOAPAction =""
In above case using request URI it is possible to find the correct service but in order to find the correct operation  it's required to build the message and look the QName of the first child under SOAPBoday this can affect to overall performance but still successful service invocation is possible.

Starting from 4.6.0 version WSO2  ESB uses new HTTP transport called pass-through which provides very high performance level, this blog post provides insights on pass-through transport but in simple terms it uses shared buffer and avoid message building at all. Now this new transport mechanism effect to above described use case -1 because now message building is not possible and hence operation dispatching is fail and messages will not process further.   We have addressed this limitation in upcoming ESB 4.8.0 version, before I describe the solution let me introduce some of the workarounds which can be used with 4.60 and 4.7.0 versions.

For ESB 4.6.0/4.7.0

1.)   Append operation name at the end of the Request URI so that request URI can be used to dispatch both service and operation.

  http://host/proxyServiceName/OperationName  


2. If it's possible modify backend JAX-WS SEI so that each operation having unique SOAPAction value.

 @WebMethod(action="XXXX")   



3. Move back to NHTTP transport instead of Pass-through in NHTTP on-demand message building is possible .

This is what you have on ESB 4.6.0

 <transportSender name="http" class="org.apache.synapse.transport.passthru.PassThroughHttpSender">  
   <parameter name="non-blocking" locked="false">true</parameter>  
 </transportSender>  
 <transportReceiver name="http" class="org.apache.synapse.transport.passthru.PassThroughHttpListener">  
   <parameter name="port" locked="false">8280</parameter>  
   <parameter name="non-blocking" locked="false">true</parameter>      
   <parameter name="httpGetProcessor" locked="false">org.wso2.carbon.transport.nhttp.api.PassThroughNHttpGetProcessor</parameter>     
 </transportReceiver>  



Replace above code using following.

 <transportReceiver name="http" class="org.apache.synapse.transport.nhttp.HttpCoreNIOListener">  
   <parameter name="port" locked="false">8280</parameter>  
   <parameter name="non-blocking" locked="false">true</parameter>  
   <parameter name="httpGetProcessor" locked="false">org.wso2.carbon.transport.nhttp.api.NHttpGetProcessor</parameter>  
   <parameter name="disableRestServiceDispatching" locked="false">true</parameter>  
 </transportReceiver>  
 <transportSender name="http" class="org.apache.synapse.transport.nhttp.HttpCoreNIOSender">  
   <parameter name="non-blocking" locked="false">true</parameter>  
 </transportSender>  


Following two diagrams illustrate runtime processing when both service and operation dispatching are required and only service dispatching required scenarios.






For ESB 4.8.0 or any future versions

Now let me discuss the improvements we have done in ESB 4.8.0.  Starting from this version users have the control  to specify whether the proxy service should expect operation dispatching or not, in situation like use case -1 now users can disable operation level dispatching and still possible to use high-speed pass-through transport.  There is a new parameter introduced called "disableOperationValidation"  to control operation dispatching on proxy service, please refer the following sample. 


 <proxy name="JAXWSServiceProxy">   
   <target>   
   <outSequence>   
    <send/>   
   </outSequence>   
   <endpoint>   
    <address uri="XXXXX"/>   
   </endpoint>   
   </target>   
   <publishWSDL uri="XXXX">   
   <parameter name="disableOperationValidation" locked="false">true</parameter>   
  </proxy>  


Now let's discuss another use case,  this one is identical to use case 1 but now we need to throttle only one operation in other words now we need to perform operation level dispatching .  It's clear in this case we need to build the message to find correct operation so the one solution would be to move back to NHTTP transport but with 4.8.0 release there is another solution introduced to build messages only if necessary, there is a new dispatcher introduced called SynapseSOAPMessageBodyBasedDispatcher which can build messages if it's required. Using following steps you can enable SynapseSOAPMessageBodyBasedDispatcher to the ESB configuration.     

1. Open a axis2.xml file

2. Locate the following entry.

       <handler class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher" name="SOAPMessageBodyBasedDispatcher"/>  


3. Replace it using  SynapseSOAPMessageBodyBasedDispatcher as follows.     

       <handler class="org.apache.synapse.core.axis2.SynapseSOAPMessageBodyBasedDispatcher" name="SOAPMessageBodyBasedDispatcher"/>  



Friday, August 02, 2013

Test all four OAuth2 grant types on WSO2 IS , WSO2 API Manager

This topic is not something new as WSO2 IS supported for both OAuth 1.0 and OAuth 2.0 specifications for sometime , instead I'm writing this post to introduce one of  OAuth2 sample application. In fact I developed this sample to understand  OAuth 2.0 specification myself and thought  to share it publicly so that someone else can used it to understand OAuth2 support on WSO2 platform. You can use this sample to test following four grant types on WSO2 IS or WSO2 APIM.


  1. Athorization Code
  2. Implicit
  3. Resource Owner
  4. Client Credentials

You can find all source codes for this sample from here https://github.com/sagaragu/OAuthWebapp



In first step you need to register a OAuth2 application either on WSO2 IS or WSO2 APIM, this step is very straightforward but if your not much clear you can follow this blog post by Prabath. Additionally same blog post introduce and explain another useful OAuth2 sample called "OAuth2 Playground2 " which you also can try, in fact before develop my sample I also use Playground2 sample to understand OAuth2 basics.


Once you register a OAuth2 application you can deploy the sample web app on any application server such as WSO2 AS or you could easily use embedded Maven Jetty plug in. Once you start the application server you can see following page and  it's straightforward to test each grant type by clicking URL on index page.




Steps required to test "Athorization Code" are given below.






















Wednesday, July 31, 2013

WSO2 ESB : Set WS-Security UT user names dynamically


Proxy services deployed on WSO2 ESB can be used to cater various security requirements, among them following two patterns are very common.



  (1) Expose an insecure  backend service as a secured service using proxy services. 




This can be done very easily by pointing to a WS - Security Policy file within the proxy configuration. In following example UTOverTransport.xml file specify the expected security configuration.  ESB admin console provides a guided wizard for this use case.


 <proxy name="SampleProxy">  
   <target>  
    <outSequence>  
      <send/>  
    </outSequence>  
    <endpoint>  
      <address uri="http://www.w3schools.com/webservices/tempconvert.asmx"/>  
    </endpoint>  
   </target>  
   <enableSec/>  
   <policy key="conf:/repository/axis2/service-groups/SampleProxy/services/SampleProxy/policies/UTOverTransport"/>  
 </proxy>   



(2)  Expose secured backend service as a insecure service so that security tokens set by the ESB.






This also can be implemented easily by pointing to a WS - Security Policy file as a QoS option at the proxy Endpoint so that ESB add required security tokens to the out-going message. I have given such example with a policy file below.


 <proxy name="HelloProxy">  
   <target>  
    <outSequence>  
      <send/>      
    </outSequence>  
    <endpoint>  
      <address uri="https://localhost:9445/services/HelloService">  
       <enableSec policy="gov:/policy/UT-Policy.xml"/>  
      </address>  
    </endpoint>  
   </target>  
 </proxy>    


In above proxy configuration security polices is defined in the UT-Policy.xml which is stored in embedded  Registry.

 <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UTOverTransport">  
     <wsp:ExactlyOne>  
       <wsp:All>  
         <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">  
           <wsp:Policy>  
             <sp:TransportToken>  
               <wsp:Policy>  
                 <sp:HttpsToken RequireClientCertificate="false"/>  
               </wsp:Policy>  
             </sp:TransportToken>  
             <sp:AlgorithmSuite>  
               <wsp:Policy>  
                 <sp:Basic256/>  
               </wsp:Policy>  
             </sp:AlgorithmSuite>  
             <sp:Layout>  
               <wsp:Policy>  
                 <sp:Lax/>  
               </wsp:Policy>  
             </sp:Layout>  
             <sp:IncludeTimestamp/>  
           </wsp:Policy>  
         </sp:TransportBinding>  
         <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">  
           <wsp:Policy>  
             <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"/>  
           </wsp:Policy>  
         </sp:SignedSupportingTokens>  
         <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">  
          <ramp:user>sagara</ramp:user>  
          <ramp:passwordCallbackClass>org.wso2.security.sample.PWCBHandler</ramp:passwordCallbackClass>  
         </ramp:RampartConfig>  
       </wsp:All>  
     </wsp:ExactlyOne>  
   </wsp:Policy>  



 If you look at above policy file carefully you can observe the user name  is hard coded as <ramp:user> and we have defined another entry called   <ramp:passwordCallbackClass>, during the runtime above user name set as the user name of UT token while PWCBHandler set the UT password related to given user name. Developers can access the user name within the PWCBHandler class and can look-up password from any convenient method such loading password from a encrypted property file or using database call etc.



One limitation of above approach is there is no way to set user name dynamically it has to be hard coded within  <ramp:user> element. But there are number of use cases where it's required to set  different user names dynamically with each message dispatching  to the proxy service. One such use case within the WSO2 platform is OAuth2 to WS-Secuty security switching using WSO2 API Manger and WSO2 ESB.


AS an example assume we have a backend service which expect WS-Security UT with in-coming messages, now let's say we have created a API in WSO2 API Manger for above backend service. The challenge with this use case is API is secured with OAuth2 Access Token but we need to extract user name and have  to set it as UT tokens before forward messages to the backend.  One possible solution for this case is given below.



  1. User invoke the API by providing a OAuth2 access tokens.
  2. After successful authentication forward messages to the ESB along with JWT token where JWT token contains authenticated user name.
  3. In ESB proxy service process the JWT token and add user name dynamically to UT token


Here the real challenge is how we could dynamically specify user name ?  for this we could use another extension point called "RampartConfigCallbackHandler"  together with a Axis2 Handler.

Step -1


Process JWT token from incoming message and set it as a property on current MessageContext. For demonstration I created a sample Handler called ExtractUserNameHandler as follows.



 public class ExtractUserNameHandler extends AbstractHandler {  
   public InvocationResponse invoke(MessageContext messageContext)  
       throws AxisFault {  
     String userName = null;  
     Map<String, String> headerMap = (Map<String, String>) messageContext  
         .getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);  
     if(headerMap != null){    
     if (headerMap.containsKey("X-JWT-Assertion")) {  
       userName = getUserNameFromJWT(headerMap.get("X-JWT-Assertion"));  
     }  
     if(userName != null){  
       addToMessageContext(messageContext, userName);        
     }  
     }  
     return InvocationResponse.CONTINUE;  
   } 
 
 
 protected void addToMessageContext(MessageContext messageContext, String userName) {  
     Map<String, String> rampConfigCBProperties = new Hashtable<String, String>();  
     rampConfigCBProperties.put("user_name", userName);  
     messageContext.setProperty("rampartConfigCallbackProperties",  
         rampConfigCBProperties);  
   } 
 
 protected String getUserNameFromJWT(String jwtToken) {  
     String[] tokenParts = jwtToken.split("\\.");  
     String user = null;  
     if (tokenParts != null && tokenParts.length == 3) {  
       byte[] jsonClaims = Base64.decode(tokenParts[1]);  
       JsonParser parser = new JsonParser();  
       JsonElement element = parser  
           .parse(new JsonReader(new InputStreamReader(  
               new ByteArrayInputStream(jsonClaims))));  
       user = element.getAsJsonObject()  
           .get("http://wso2.org/claims/enduser").getAsString();  
       System.out.println("user name : " + user);  
       return user;  
     }  
     return null;  
   }  
 }    


Step -2


Now we can implement RampartConfigCallbackHandler interface and possible to read the value from MessageContext so that we can dynamically add the user name to the security configuration.


 public class RampartConfigCallbackHandlerImpl implements  
     RampartConfigCallbackHandler { 
public void update(RampartConfig config) {  
     Map<String, String> propertyMap = config.getPropertyMap();  
     if (propertyMap != null && propertyMap.containsKey("user_name")) {  
       System.out.println(" adding user name : "+ propertyMap.get("user_name"));  
       config.setUser(propertyMap.get("user_name"));  
     }  
     config.setPwCbClass("sample.PWCBHandler");  
   }  
 }  

Step -3


Still we need  to provide a WS-Policy file which specify the above created RampartConfigCallbackHandlerImpl class.


 <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"  
   xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"  
   wsu:Id="UTOverTransport">  
   <wsp:ExactlyOne>  
     <wsp:All>  
       <sp:TransportBinding  
         xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">  
         <wsp:Policy>  
           <sp:TransportToken>  
             <wsp:Policy>  
               <sp:HttpsToken RequireClientCertificate="false" />  
             </wsp:Policy>  
           </sp:TransportToken>  
           <sp:AlgorithmSuite>  
             <wsp:Policy>  
               <sp:Basic256 />  
             </wsp:Policy>  
           </sp:AlgorithmSuite>  
           <sp:Layout>  
             <wsp:Policy>  
               <sp:Lax />  
             </wsp:Policy>  
           </sp:Layout>  
           <sp:IncludeTimestamp />  
         </wsp:Policy>  
       </sp:TransportBinding>  
       <sp:SignedSupportingTokens  
         xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">  
         <wsp:Policy>  
           <sp:UsernameToken  
             sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">              
           </sp:UsernameToken>  
         </wsp:Policy>  
       </sp:SignedSupportingTokens>  
       <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">  
         <ramp:rampartConfigCallbackClass>sample.RampartConfigCallbackHandlerImpl  
         </ramp:rampartConfigCallbackClass>  
       </ramp:RampartConfig>  
     </wsp:All>  
   </wsp:ExactlyOne>  
 </wsp:Policy>  






Friday, January 25, 2013

Setting HTTP basic security in Maven Jetty plug-in

Recently I had to test HTTP basic security for one of my web application project, just to save my time I didn't want to use any standalone server during development instead I tried to configure Maven Jetty plug-in to support HTTP basic security. Here I have given the procedure which I followed.

1.) Configure Maven Jetty plugin in project pom.xml file.

It's required to add a UserRealm under plug-in configuration section. Jetty provides number of in-built UserRealms, here I used HashUserRealm for simplicity which use in-memory HashMaps to store users and roles.

 <plugin>  
                     <groupId>org.mortbay.jetty</groupId>  
                     <artifactId>maven-jetty-plugin</artifactId>  
                     <configuration>  
                          <scanIntervalSeconds>3</scanIntervalSeconds>  
                          <webAppConfig>  
                               <contextPath>/</contextPath>  
                          </webAppConfig>  
                          <userRealms>  
                               <userRealm implementation="org.mortbay.jetty.security.HashUserRealm">  
                                    <name>basic security</name>  
                                    <config>jetty-users.properties</config>  
                               </userRealm>  
                          </userRealms>  
                     </configuration>  
                </plugin>  
           </plugins>  



Then add a property file called jetty-users.properties which contains user names, passwords and user roles.

 sagara=sagara,ADMIN  



2.) Configure web.xml file of the web application.

In this example we allow users with ADMIN role to access any URL within the application. 

 <security-constraint>  
           <display-name>authorizedUsers</display-name>  
           <web-resource-collection>  
                <web-resource-name>ALL URLs</web-resource-name>  
                <url-pattern>/*</url-pattern>  
           </web-resource-collection>  
           <auth-constraint>  
                <role-name>ADMIN</role-name>  
           </auth-constraint>  
      </security-constraint>  
      <login-config>  
           <auth-method>BASIC</auth-method>  
           <realm-name>basic security</realm-name>  
      </login-config>  
      <security-role>  
           <description>administrator access</description>  
           <role-name>ADMIN</role-name>  
      </security-role>  

Friday, May 04, 2012

Release of Axis2 1.6.2 and Sandesha2 1.6.2 , Rampart 1.6.2

The Apache Axis2 team is pleased to announce the general availability of the following releases:


  • Axis2 1.6.2
  • Sandesha2 1.6.2
  • Rampart 1.6.2


Apache Axis2 is a complete re-design and re-write of the widely used Apache Axis engine and is a more efficient, more scalable, more
modular and more XML-oriented Web services framework. It is carefully designed to support the easy addition of plug-in "modules" that extend
its functionality for features such as security and reliability.

Apache Rampart is an Axis2 module that implements the specifications in the WS-Security stack.

Apache Sandesha2 provides WS-ReliableMessaging support for Axis2.

Axis2 1.6.2 is a maintenance release that contains more than 45 fixes.

Rampart 1.6.2 is a maintenance release containing number of bug fixes and compatible with the Axis2 1.6.2 release.

Sandesha2 1.6.2 is a maintenance release that is compatible with the Axis2 1.6.2 release.

The new versions are available for download at the following locations:

http://axis.apache.org/axis2/java/core/download.cgi
http://axis.apache.org/axis2/java/rampart/download/1.6.2/download.cgi
http://axis.apache.org/axis2/java/sandesha/download.cgi

As always, we welcome any and all feedback at:

java-dev@axis.apache.org - for developer-related questions/concerns
java-user@axis.apache.org - for general questions, usage, etc.


NOTE  - Axis2 1.6.2 compatible with Axis2 Transports 1.0.0 version


Thursday, May 03, 2012

Code generation and WSDL exposed over HTTPS


In one of my previous post I explained how to use WSDL2JAVA tool  behind a proxy together with basic authentication. Another such  useful scenario is code generation for a WSDL which exposed over HTTPS protocol.  In this case we have to provide key store details to the WSDL2JAVA tool. Basically it expect following two Java system properties.

 javax.net.ssl.trustStore  
 javax.net.ssl.trustStorePassword  
Once you know those properties you can use WSDL2JAVA tool as follows.
    
 wsdl2java.sh -uri https://localhost:8443/services/SimpleService?wsdl -Djavax.net.ssl.trustStore=path/keystorename.keystore -Djavax.net.ssl.trustStorePassword=keypassword