Popular Posts

Sunday, February 24, 2008

Securing Axis2/WSAS web services with Username token

Security is a crucial requirement in distributed computing. When it comes to web services, it is even more important. Apache rampart is the module which is used to secure an Axis2 web service. There are numerous approaches to secure your Axis2 web service using rampart module. Username token authentication can be considered as the simplest mechanism to protect your service. Lets see how the username token authentication is enabled in your web service and write a client easily using WSO2 WSAS which dramatically simplifies most of the complex steps.

I will demonstrate the scenario using WSO2 WSAS 2.2.1. You can follow most of the steps given here with Axis2 as well.
Lets assume WSO2 WSAS is configured in your system and it is up and running. (See WSAS installation guide if you want to know how WSAS is deployed).

Step 1
Access WSAS management console using https://localhost:9443 and log in using default admin credentials (admin/admin).

I'm going to explain how to secure one of the default services deployed on WSAS using username token authentication mechanism. Therefore, we have to create a user who will be granted permission to invoke the service.

Go to users-->user management screen and create a new user (i.e username=charitha, password=charitha).



Step 2

Now we need to enable security on one of the services available in WSAS management console. Select 'version' service in services and service group management page. You will be directed to the service management page of the version service. Select 'Manage security configuration' link.
Following page will be displayed where you can select 'UsernameToken with Timestamp over HTTPS' option.


Now you should be in the Services> version>Security Configuration> scenario1' page. Assign the user(charitha) which has been created in the previous step to version service. If everything is successful you will get "Security scenario successfully applied" message.

We have seen how WSO2 WSAS simplified assigning a security configuration to our web service. You will see that version service is exposed only through https transport after assigning the UT scenario. Also, you can check the security policy which has been generated by WSAS if you click on 'Edit service policies' link in the service management page.



The server side security configuration has been completed by now. Lets write a java client and invoke the service securely!

Step 3

WSAS provides a very useful code generation utility which can be used to generate a client stub easily. Select version service and click on 'Generate Client' link. You will be directed to 'Services>version>Stub generation' page. Set unpack class option to false and click on 'Generate' by leaving the other default options.
Save the generated client jar file in your file system.

Step 4

Next, we need to provide user authentication information to the client. We are going to configure our java client through a client side security policy. Therefore, we need to write our policy.xml and client needs to be written to read that policy. I'm not going to describe all the information available in client security policy. Please download policy.xml from here and save it in your file system. In the mean time, we should have a look at the RampartConfig element in policy.xml because it is where we configure the user information.
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:user>charitha</ramp:user> <ramp:passwordCallbackClass>org.test.PWCBHandler</ramp:passwordCallbackClass>

</ramp:RampartConfig>

Here you can see that password of the user is supplied through a PasswordCallBack handler class (PWCBhandler in our example).

public class PWCBHandler implements CallbackHandler { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i <> WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i]; if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) { if(pwcb.getIdentifer().equals("charitha") && pwcb.getPassword().equals("charitha")) { return; } else { throw new UnsupportedCallbackException(callbacks[i], "check failed"); } } pwcb.setPassword("charitha"); } } }

Compile and save the callbackhandler class and make it available in your client class path.

Step 5

We are going to complete our scenario by constructing the client using the generated stub in step 4.
In our client, first we need to set the system properties for SSL since we are going to access version service via https. (Please modify keystore path according to your file system)


System.setProperty("javax.net.ssl.trustStore","C:\\wsas\\wsas-2.2.1\\wso2wsas-2.2.1\\conf\\wso2wsas.jks"); System.setProperty("javax.net.ssl.trustStorePassword", "wso2wsas");

We need to instruct our client to use rampart module, we cannot simply add a mar(module archive) to our class path. Therefore we can create a configurationContext instance using file system and use it as follows.
ConfigurationContext ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem("C:\\wsas\\client-repo\\", null);

Next, create an instance of version service stub with passing the above Configurationcontext as an argument in the constructor.
VersionStub stub = new VersionStub(ctx, "https://192.168.1.2:9443/services/version");

Rampart module can be engaged in client as follows.

stub._getServiceClient().engageModule("rampart");

Next, the policy.xml which has been defined in step 4 needs to be loaded. We can do that using ServiceClient options class by setting it as a property.

Options options = stub._getServiceClient().getOptions();
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY, loadPolicy("C:\\wsas\\client-repo\\policy.xml"));
stub._getServiceClient().setOptions(options);

private static Policy loadPolicy(String xmlPath){
StAXOMBuilder builder = new StAXOMBuilder(xmlPath);
return PolicyEngine.getPolicy(builder.getDocumentElement());
}

Everything is ready! We can run our client now. Make sure to add jars included in WSO2WSAS_HOME/lib to your class path.
You can download source of the client from here.








Thursday, February 14, 2008

The simplest method of deploying an Axis2 web service

I think Apache Axis2 is the most effective, efficient and useful open source java web service framework ever written. Not only that, if you are new to Java web services, Axis2 provides a lot of handy tools and mechanisms in order to start exploring WS technology. One of the easiest way of learning Axis2 is start with POJO (Plain old Java objects). You may wonder that you can deploy a java class as an Axis2 service in one line of code!!!
Lets have a look...

1. Write a java class

2. Add following line inside the main method of your class
new AxisServer().deployService(SimplePojo.class.getName());

Make sure to add Axis2 libraries in your class path. (Axis2-1.3 can be downloaded from here)

3. Open your favorite browser and issue http://localhost:6060

4. You will see that your java class is exposed as an web service.

Here is the complete sample code which can be copied to your IDE and play with it.

package org.test;

import org.apache.axis2.AxisFault;
import org.apache.axis2.engine.AxisServer;

public class SimplePojo {

public int addnumbers(int x, int y){
return x+y;
}

public static void main(String[] args)throws AxisFault {
new AxisServer().deployService(SimplePojo.class.getName());
}
}

Tuesday, February 12, 2008

Finding critical bugs at the critical moments of a release

The issues of a product can typically be revealed during the functional/regression test cycles. Most of the text books and web resources written about SQA, suggest to follow a properly designed test processes in order to catch bugs as early as possible. I strongly agree with that. However it is not always a practical approach to adhering to that kind of process. In my experience, more bugs are uncovered and caught by test teams when the product is matured and the team is familiar and well aware of the functionality of the product. One may argue that the good test design should anticipate all possible scenarios. However, it is not always true. Most of the practical and useful test scenarios are captured during the test execution stage NOT in the design phase.
I'm not going to say that QA doesn't have to be part of early planning and reviewing to find out issues. it will definitely help to capture design level defects as well as preparing test cases and scenarios. However, even with all efforts, you will encounter the last minute issues when product is mature and fully integrated, also QA have enough knowledge about the product in user's perspective.
Therefore last minute issues are not strange, specially in the modern agile development processes.
In my experience, one of the most important aspect of agile QA is to reveal critical issues as quicker as possible at any stage of the development cycle. In agile methodologies, QA do not get the luxury of following a proper release cycles and sufficient schedule for comprehensive testing. Therefore, QA should be in a position to capture critical bugs in a quicker way whenever a new build is given for testing.
So, what does it mean by finding critical bugs at the critical moments of a release?

Suppose, you are assigned to test a software product which has already undergone number of functional and regression testing cycles. Therefore, the critical issues are minimum in that kind of a product. Assume, a simple performance fix has been done in order to improve concurrency handling of the product and a minor release is expected to be done within a day. In such situation, a traditional QA process may suggest to do a smoke test to ensure the existing functionalities are not affected by that fix. Yes. That is important. However, QA should be able to try out a set of ad-hoc scenarios in order to capture some hidden issues which may have arisen due to the performance fix. QA/test engineers should use their experience to carry out some random checks to ensure that the quality of the product is not affected by the fix. There are situations where QA do not even get enough time to do a full smoke test. In such situations, QA can act wisely with the product knowledge and common sense to find out regression issues as quicker as possible.
In other words, QA should have a better understanding on exploratory testing. I will post a new blog entry on my experience in exploratory testing in due course.

Wednesday, February 6, 2008

Exposing a spring bean as a web service

One of the major requirements expected from a web service framework is to expose the existing business components as web services. Spring framework has been using for Enterprise Application development for many years as it provides a more simpler approach than traditional J2EE application development.
WSO2 Web services application server provides an easy-to-use and efficient mechanism for exposing your Spring beans as java web service in a jiffy.

Pre-requisites:
WSO2 web services application server - WSAS2.2 (Download)

Step 1
As the first step, we should implement the Spring class (pojo) which needs to be exposed as the web service. I will write a very simple pojo which has one In-Out method as follows.

package org.ws.test;

public class Inoutbean {

public String echo(String s){
return s;
}

}
Compile and save the class.

Step 2

Now, we need to create the associated spring configuration file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="InoutSpringBean" class="org.ws.test.Inoutbean">
</bean>
</beans>

Save the file as spring.xml

Step 3

Bundle the spring class in a jar so that it can be deployed on WSAS. Say the jar file is SpringBeans.jar

Steps 4
Start WSO2 Web services application server (WSAS) and access its management console using https://localhost:9443
Next, select 'Services' from the left navigation menu. You will be directed to the
'Service & Service Group Management' page.
Click on 'Upload Spring service' link.



Step 5
Next, select the SpringBeans.jar and the spring.xml and click on upload. You will be directed to the following screen.



You can select the spring bean from this screen and click on 'Generate' to complete the deployment.

Step 6
Now, the service deployment task is over and you can verify the service invocation with Tryit utility. Or else, just send a REST request as follows and check whether the expected output is returned in your browser
http://localhost:9762/services/InoutSpringBean/echo?s=hi

You may have noticed the ease-of-use when exposing a spring bean through WSO2 WSAS. The same procedure can be applied for any complex spring beans.
Before completing our scenario, you may have a look at the generated service archive by WSAS. It will reside at WSAS_HOME/repository/services. Open the 'SpringBeans.aar' and check the /META-INF/services.xml. You will see the following element there.
<parameter locked="true" name="ServiceObjectSupplier">org.wso2.wsas.admin.service.spring.GenericApplicationContextSupplier</parameter>
This is the most important entity of spring service generation and it instructs WSAS to load the Spring beans from the Spring configuration file.