Popular Posts

Sunday, February 14, 2010

How to invoke a secured web service without maintaining a policy at the client side

When we call a secure web service, the most common way of invocation is to use a policy which is compliant with the service policy at the client side. Usually, the client side policy is placed at the client file system. We have observed how this is done in few posts which published earlier.
However, there is a major drawback in this method, user has to change the client policy whenever the service policy is changed.
In order to overcome this limitation, we can use Axis2 DynamicClient to derive client policy by referring to the service WSDL which essentially keeps the service policy.

Lets see how this can be done using WSO2 WSAS-3.1.*

Pre-requisite:

Download and install WSO2 WSAS-3.1.*

Step 1

We are going to secure the default HelloService shipped with WSAS. We configure HelloService with "Sign and Encrypt - X509 Authentication" policy. In order to do that, first start WSO2 WSAS server by running wso2server.sh which is located at WSO2WSAS_HOME/bin directory.
Then, log in to the management console by accessing https://localhost:9443/carbon

Select the default HelloService and navigate to the service dashboard. Click on Security and configure Sign and Encrypt - X509 Authentication security scenario as shown below. Make sure to use wso2carbon.jks as trusted key store and private key store.



Thats all we have to do at the server side. Lets write a client to invoke the service.

Step 2

Here we are going to use Axis2 Dynamic Client which is an extension of the ServiceClient class.
First, instantiate a dynamicClient object using RPCServiceClient by passing ConfigurationContext, WSDL Url of the service, the QName of the service and the port name as parameters.

RPCServiceClient dynamicClient = new RPCServiceClient(null, new URL("http://localhost:9763/services/HelloService?wsdl"),
new QName("http://www.wso2.org/types", "HelloService"), "HelloServiceHttpSoap12Endpoint");

Then, we can engage rampart module as follows.
dynamicClient.engageModule("rampart");
Now we should update the client side policy with the rampart-config programatically.


RampartConfig rc = new RampartConfig();

rc.setUserCertAlias("wso2carbon");
rc.setEncryptionUser("wso2carbon");
rc.setPwCbClass(SecureClient.class.getName());

CryptoConfig sigCryptoConfig = new CryptoConfig();

sigCryptoConfig.setProvider("org.apache.ws.security.components.crypto.Merlin");

Properties prop1 = new Properties();
prop1.put("org.apache.ws.security.crypto.merlin.keystore.type", "JKS");
prop1.put("org.apache.ws.security.crypto.merlin.file", "/home/charitha/products/wsas/wso2wsas-3.1.3/resources/security/wso2carbon.jks");
prop1.put("org.apache.ws.security.crypto.merlin.keystore.password", "wso2carbon");
sigCryptoConfig.setProp(prop1);

CryptoConfig encrCryptoConfig = new CryptoConfig();
encrCryptoConfig.setProvider("org.apache.ws.security.components.crypto.Merlin");

Properties prop2 = new Properties();

prop2.put("org.apache.ws.security.crypto.merlin.keystore.type", "JKS");
prop2.put("org.apache.ws.security.crypto.merlin.file", "/home/charitha/products/wsas/wso2wsas-3.1.3/resources/security/wso2carbon.jks");
prop2.put("org.apache.ws.security.crypto.merlin.keystore.password", "wso2carbon");
encrCryptoConfig.setProp(prop2);

rc.setSigCryptoConfig(sigCryptoConfig);
rc.setEncrCryptoConfig(encrCryptoConfig);

Next, we can add the above rampartConfig to the service policy derived from the wsdl as follows.


Map endPoints = dynamicClient.getAxisService().getEndpoints();
AxisBinding axisBinding = ((AxisEndpoint) endPoints.values().iterator().next()).getBinding();
Policy policy = axisBinding.getEffectivePolicy();
policy.addAssertion(rc);
axisBinding.applyPolicy(policy);
Now, we can invoke the service using dynamicClient by passing the parameters as an object array and return types as an class array.


Object[] returnArray = dynamicClient.invokeBlocking(new QName("http://www.wso2.org/types", "greet"),
new Object[]{"hello"}, new Class[]{String.class});

System.out.println(returnArray[0]);


Thats all! To complete our scenario, make sure to have callback handler method similar to the one below.



public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[0];
String id = pwcb.getIdentifer();
if ("wso2carbon".equals(id)) {
pwcb.setPassword("wso2carbon");
}

Sunday, February 7, 2010

Visits to this blog - 2009 (significant increase of visitors)

I published a stat report about this blog in February 2009, which showed 30037 unique visitors during 2008-2009. Here is the StatCounter report for 2009-2010.




There were 55,839 unique visitors, 25000 increase compared to last year. I could not write much blog posts during the last year due to frequent project releases. However which did not seem to affect my user community. This blog was started to help novice users in SOA/Web Service space and Software Quality Assurance community to share my ideas, tips and specially How-Tos. I always refrained from posting any non-technical subject matter in here. I was able to reply most of the questions raised in blog posts, however there were situations that I could not follow the comments and reply. I will try my best to continue writing much more useful blog posts and help users.

Saturday, February 6, 2010

WSO2 QA Test Framework - Fundamentals

WSO2 QA Test framework has been developed to replace repetitive manual test procedures followed during the release cycles. We identified the tests which provide much ROI with automation and used them for phase1 of the test framework development project.
With the introduction of WSO2 Carbon product platform in late 2008, all java based products are implemented using the base carbon platform. All products (9 all together) are released at the same day which is a very different experience specially for a QA team. All products are supposed to go through a set of common tests and a set of product specific tests. All are supposed to work on multiple application servers, multiple JVMs, multiple browsers, multiple operating systems, multiple DBMSs etc.. hell a lot of test combinations! The product count exceeded the number of people in test team. More products are expected to be introduced in near future. Therefore, the only viable solution to manage the QA process is to automating as more tests as possible.
So, we started implementing our automated test framework in 2009 March.
As I discussed in some previous posts, we chose selenium for automation. We used Selenium Remote Control Java client driver to drive selenium tests with Junit. However our tests were not restricted to web based selenium scripts. We have written numerous tests which used Axis2 ServiceClient API and some other API methods to invoke web services, sending messages via secure channels, reliable messaging, message mediation etc.
We derived our project structure which adheres to maven as given below. You can get a SVN checkout of 2.0.3 branch of the test framework (which is the most stable version at the moment) from https://wso2.org/repos/wso2/branches/commons/qa/web-test-framework/2.0.3

common
bps
registry
wsas
esb
gs
mashup
is
ds

Each project is built using its pom.xml at the root of the project directory. We used selenium maven plugin and surefire plugin to start selenium RC server and launch Junit tests respectively.
commons project is used to maintain tests which are used in all products. For example, org.wso2.carbon.web.test.common.RegistryBrowser is common for all products since all products have a common registry browser. We used svn:externals to link the common classes to relevant projects.
You can find all common classes at https://wso2.org/repos/wso2/branches/commons/qa/web-test-framework/2.0.3/commons/src/test/java/org/wso2/carbon/web/test/common/

In addition to that, commons project is used to store the test artifacts which are shared among multiple products. For example JDBC connector jars and keystores are used in all products and those are stored in commons/lib directory.

The other most important resource included in commons project is framework.properties configuration file. It is used to configure the test framework according to the test environment. Under the "global properties" section of the framework.properties file, you could find the following properties.

host.name=172.16.37.1
http.port=9763
https.port=9443
carbon.home=/home/charitha/products/wsas/wso2wsas-3.1.3
context.root=/wsas
browser.version=firefox
admin.username=admin
admin.password=admin
module.version=2.03

You must change these properties as per your test environment settings. http.port and https.port are the embedded tomcat servlet transport ports used in WSO2 Carbon products. (full explanation of these properties will be included in a future post)

Lets look at a product specific test suite. Go to wsas directory in your test framework checkout. This is the project used to run WSO2 WSAS specific tests. You will find the following files and directories at the root of this project.

lib
src
pom.xml
runAll.sh
runAll.rb
wsas_test_suites.txt

lib directory is used to store the test artifacts specific to WSAS such as axis2 services, jaxws services etc.
You can invoke tests using two different ways.

  • Direct maven invocation - you can run tests individually by passing a system property as follows
mvn clean install -Dtest.suite=usermanagement

  • Run tests through a shell script - You can run tests individually or as a whole suite or few tests at once using this way. Here, it is required to uncomment the selected tests in wsas_test_suites.txt. The runAll.sh shell script read the test names from wsas_test_suites.txt and invoke each test.
sh runAll.sh

In any of the above mechanisms, we call a central test suite class which takes care of calling the individual tests. For each project we have a separate AllTests.java class which extends junit.framework.TestSuite parent. In our example, org.wso2.carbon.web.test.wsas.AllTests.java is the TestSuite.

See https://wso2.org/repos/wso2/branches/commons/qa/web-test-framework/2.0.3/wsas/src/test/java/org/wso2/carbon/web/test/wsas/AllTests.java for more details about this class.

You will also notice in AllTests class that initBrowser() method of the BrowserInitializer class is called to launch the browser instance for a particular test as follows.

public synchronized static void initBrowser()throws Exception{


if (browser == null) {
browser = new DefaultSelenium("localhost", 4444, "*"+property.getProperty("browser.version"), "https://" + property.getProperty("host.name") + ":" + property.getProperty("https.port"));
browser.start();
browser.setSpeed("200");

}
}

You can easily try out WSO2 QA test framework once you download and start using any of WSO2 Carbon based product. This is not a detailed explanation of the all features available in our test framework. I will guide you through more information in future posts. If you encounter any issues while using the test framework, please drop us a mail - architecture@wso2.org

Stay tuned.. will post more on automation soon!

Thursday, February 4, 2010

Google Automation - Automated testing search engine


If you are looking for software test automation information, you will get the best results by using Google Automation search engine. It only searches the sites that matter most to automators.

Wednesday, February 3, 2010

How to start WSO2 Carbon AMIs

The latest product versions of WSO2 SOA platform are available for download now. This release addresses various bug fixes and enhancements. In addition to the usual binary, source and document distributions, WSO2 products are now available as cloud virtual machines.
WSO2 cloud virtual machines provides you with the ability to implement your SOA infrastructure in private or public cloud. In this post, we will look at how AMIs of WSO2 Carbon family of products can be used.
I will use WSO2 ESB AMI for the demonstration, however you can follow the same steps to start any of the WSO2 Carbon AMI.

Pre-requisite:
You should have the necessary Amazon EC2 account ready for AMI administration. AMI EC2 API tools should be installed in your computer. You may refer to this tutorial in order to set up the infrastructure.

Step 1
Go to WSO2 ESB home page in Oxygen Tank. Click on WSO2 Cloud Service under the Download icon.
You will find WSO2 ESB cloud virtual machines in that page. Take a note of AMI ID given there (ami-878569ee)

Step2
Open a shell and issue the following command to start 64bit WSO2 ESB AMI instance.

ec2-run-instances ami-878569ee -k --instance-type m1.large

Replace with the name of your public/private keypair. Read http://docs.amazonwebservices.com/AmazonEC2/gsg/2006-06-26/running-an-instance.html if you do not know hot to generate a keypair.


Step 3

The above command starts up an AMI instance with a pre-configured WSO2 ESB server. Also, the above will return the ID of the started instance (instance-id).

e.g:-

INSTANCE i-c28093aa ami-878569ee pending charithakankanamgewso2-keypair 0 m1.large 2010-02-04T06:03:25+0000 us-east-1c aki-a3d737ca ari-7cb95a

After a few seconds, issue the following command to get the public DNS name of WSO2 ESB so that we can access ESB management console.

ec2-describe-instances

e.g:- ec2-describe-instances i-c28093aa

This will return the public DNS name as follows.

INSTANCE i-c28093aa ami-878569ee ec2-174-129-86-140.compute-1.amazonaws.com domU-12-31-39-0C-21-B2.compute-1.internal

Step 4

Open a browser and access URL, https://ec2-174-129-86-140.compute-1.amazonaws.com. You will be able to log in to WSO2 ESB management console.






Tuesday, February 2, 2010

Importance of logging in QA testing

Recently James Bach posted a nice blog entry in which he identified logging as a good friend of an exploratory test team. I believe the comprehensive logging of AUT (application under test) is an extremely valuable asset to any tester regardless of the context of exploratory testing.
A detailed log will surely help to minimize the effort required to reproduction of issues. There are intermittent failures, random application crashes which are extermely hard to regenerate in successive attempts. If the AUT is written in a way in which all the major user events are logged, then the root causes of such random failures can be traced easily.
A comprehensive log is a useful test report. After a test run, you can store the log somewhere safely and use it as the test report. Specially, in agile test processes, test teams do not find sufficient time to record test results and maintain detailed test reports due to the short release cycles. If the AUT provides good set of logs, it will help testers to use them instead of maintaining separate test logs.

IMHO, comprehensive logging is a must have feature of any of the enterprise-scale application. At WSO2, this has been identified as a extremely important tool and the necessary modifications are in-progress to improve logging in WSO2 Carbon SOA middleware suite.