Sunday, August 9, 2015

Authenticating tenants and users in a web app deployed in WSO2 Application Server

WSO2 Application Server can be used to deploy and host standard web applications. WSO2 Application server runs on top of Carbon platform which provides the user and tenant management features as well. If you want the web application you deploy (in super tenant mode), to include user authentication (user login), you can leverage the API s provided by the Carbon platform. Relevant services are available as OSGi services, and you can do an OSGi lookup to obtain the required services.

Refer the code segment (jsp) below.

In the UI I have two text boxes to provide username and password.

If domain name is not specified in the username, it assumes a login of a super tenant or a super tenant user (hence domain is set to carbon.super). For tenant admins and users, relevant domain needs to be specified, and relevant tenant's UserRealm is loaded using the method AnonymousSessionUtil.getRealmByTenantDomain

For more about PrivilegedCarbonContext, refer here
     

<%@ page import="org.wso2.carbon.context.CarbonContext" %>
<%@ page import="org.wso2.carbon.context.PrivilegedCarbonContext" %>
<%@ page import="org.wso2.carbon.user.api.UserRealm" %>
<%@ page import="org.wso2.carbon.user.core.service.RealmService" %>
<%@ page import="org.wso2.carbon.user.api.UserRealmService" %>
<%@ page import="org.wso2.carbon.user.api.UserStoreException" %>
<%@ page import="org.wso2.carbon.user.api.UserStoreManager" %>
<%@ page import="org.wso2.carbon.core.util.AnonymousSessionUtil" %>
<%@ page import="org.wso2.carbon.registry.core.service.RegistryService" %>

<%! String removeTenantDomain(String userName) {
  if(userName.contains("@")) {
      String[] arr = userName.split("@");
      return arr[0];
     }
  return userName;
}
%>

<%
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String tenantDomain = "carbon.super";
    boolean status = false;
    if (username != null && username.trim().length() > 0) {
        try {
            
            PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            RealmService realmService = (RealmService) carbonContext.getOSGiService(RealmService.class);
            RegistryService registryService = (RegistryService) carbonContext.getOSGiService(RegistryService.class);
                     
            // If domain is specified
            if(username.contains("@")) {
             String[] arr = username.split("@");
             tenantDomain = arr[1];
             
            }
            UserRealm realm = AnonymousSessionUtil.getRealmByTenantDomain(registryService,realmService,tenantDomain);
            status = realm.getUserStoreManager().authenticate(removeTenantDomain(username), password);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    if (status) {
        session.setAttribute("logged-in", "true");
        session.setAttribute("username", username);
        response.sendRedirect("login.jsp");
    } else {
        session.invalidate();
        response.sendRedirect("login.jsp?failed=true");
    }
%>

How to do a URL encode in WSO2 ESB

I have recently came across a requirement to send an XML paylod in URL encoded format to the backend. I was able to get it done with WSO2 ESB script mediator

Request to ESB is as follows:
<request><user>Sajith</user></request>


Backend expects the request as follows
http://localhost:8001/myservice?RequestXML=%3CRequest%3E%3CUser%3ESajith%3C%2FUser%3E%3C%2FRequest%3E


This was achieved by the following code. (Using javascript method encodeURL)
     <script language="js" description="">
         mc.setProperty("uri.var.encodedBody", encodeURI(mc.getPayloadXML()));
     </script>

     <send>
         <endpoint>
             <http method="post" uri-template="http://localhost:8001/myservice?RequestXML={uri.var.encodedBody}"/>
         </endpoint>
     </send>

Wednesday, May 13, 2015

Setting up a VM cluster in VirtualBox

You may come across a requirement to setup a cluster of virtual machines which need to be able to communicate among themselves as well as to access internet within each virtual machine instance. With the default network settings in VirtualBox you won't be able to achieve inter-VM communication. For that you need to setup a Host-only adapter.

Go to VirtualBox UI, File --> Preferences --> Network --> Host-only networks

Click "Add", and fill out IPV4 address as 192.168.56.1 and Network Mask 255.255.255.0. In the DHCP Server tab, untick enable DHCP server to disable it.



Now we have configured the host-only adapter. We can use this adapter when creating new virtual machines.

My requirement is to setup 2 virtual machines with the IP s 192.168.56.20 and 192.168.56.21.
I will show you how to setup one virtual machine.

Select the virtual machine you need to configure your network settings, and click on "Settings" icon --> Then click on "Network", you will get a UI as follows.


There, you tick on "Enable Network Adapter", Select Host-only Adapter in Attached to dropdown, and select the hostonly adapter that we configured earlier (vboxnet0) Click on the next tab to configure NAT, as follows.


Now you have configured both host-only and NAT Start your virtual machine.
 But still, if you do an "ifconfig" from your virtual machine you will not see any 192.168.xx ip has assigned. You need to do one more setting as follows.

Go to /etc/network/interfaces file and add following.

 #---------------------------------------
 auto lo
 iface lo inet loopback

 # Host-only interface
 auto eth0
 iface eth0 inet static
     address 192.168.56.20
     netmask 255.255.255.0
     network 192.168.56.0
     broadcast 192.168.56.255

 #-----------------------------------------

Restart your virtual machine and now you will see your 192.168.56.20 interface is up. Same way, you can configure your 192.168.56.21 virtual machine and so on....

You can ping from 192.168.56.21 machine to 192.168.56.20 and vise-versa

Wednesday, March 25, 2015

Convert request parameter to an HTTP header in WSO2 ESB



Say, you have a requirement to pass a request parameter (named key) which comes to an ESB proxy service, and that need to be passed to the backend service as an HTTP header (named APIKEY).

Request to ESB proxy service would be as follows.
      curl -X GET "http://localhost:8280/services/MyPTProxy?key=67876gGXjjsskIISL

In that case you can make use of xpath expression $url:[param_name]

In your in-sequence you can add a header mediator as follows to set the HTTP header with key request parameter



Friday, March 20, 2015

Java based CLI client to install WSO2 carbon features

WSO2 Products are based on WSO2 Carbon platform + set of features. (Carbon platform is also a collection of features) So, WSO2 products are released with set of pre-bundled features. For example, WSO2 Identity Server comes with System and User Identity Management feature, Entitlement Management features etc. API Manager comes with API management features, and features related to publishing and managing APIs etc. There can be requirement where the Key management features found in API Manager, need to be handled in the Identity Server itself, without going for a dedicated API Manager (Key manager) node. In such a scenario, you can install key management features into Identity Server.

Feature installation / management can be done via Management console UI [1] or using pom files [2]

In this blog post I'm presenting another way of installing features, that is via a Java based client.

This method can be used in situations where you have an automated setup to provision nodes with required features. You can find the code for that client in github.

[1] https://docs.wso2.com/display/Carbon420/Installing+Features+via+the+UI
[2] https://docs.wso2.com/display/Carbon420/Installing+Features+using+pom+Files

Thursday, December 18, 2014

Puppet configs

Puppet master
    server name in /etc/puppet/puppet.conf is not needed
    set autosign=true in /etc/puppet/puppet.conf

Obtain the puppet master hostname by executing  "hostname -f"

Puppet agent
    Set the proper puppet hostname in /etc/puppet/puppet.conf which is obtained in the previous command, if that is resolvable. Otherwise need to add that hostname into /etc/hosts file
    agent's hostname can be any value. No need to have master's hostnames init. puppet agents hostname need to be resolvable. for eg, to 127.0.0.1


   

Wednesday, October 8, 2014

Code Analysis with SonarQube Eclipse Plugin


SonarQube is a cool platform which helps to maintain code quality of a project, through integration of several code analysis tools like PMD, FindBugs, Checkstyle etc. Code quality of Apache Stratos
project is also measured and maintained through SonarQube.

Committers and contributors of Apache Stratos project are advised to have their code analysed through SonarQube before committing any new code or sending a PR.

There is an Eclipse plugin which makes developers' life easier, to run an analysis and find out code if there's any code quality issues, and fix without moving away from Eclipse.

I have recently written a wiki entry on how to configure and use SonarQube Eclipse plugin to analyse your code for Apache Stratos, you can find it here