Wednesday, December 30, 2015

OpenMRS World Wide Summit as It Happened



It's nearly four years I'm hanging around OpenMRS. So far it has been a wonderful journey. I still remember the days that I have started with OpenMRS in 2012 which ended up been a GSoC student in 2013. The reason that I have wanted to contribute to OpenMRS is beacuse the contributions that we made account for save peoples' lives and make the lives better. It's a pain to maintain hand written patient records within  a hospital system. Due to various disasters such as floods, fire and the animal activities cause paper based medical records to be damaged which can't be used again. Also medical records are very important to track patient history and the record data can be used to analyze patterns and causes for the diseases which useful in find treatments and precautions to avoid such a diseases. I can be very happy with my contributions as it leads to help thousands of people who use OpenMRS. 

I was fortunate to attend OpenMRS Implementer meeting in Eldoret, Kenya in 2013. OpenMRS has funded for my whole journey which I should be grateful. I was lucky to see the AMPATH where the OpenMRS has born. Also I had the chance to meet my GSoC mentor Jeremy Keiper during the summit. I was never think that I can meet my GSoC mentor. I have met contributors and implementers who I have interact within community. It was great to meet them personally. 

Continuing my journey, I have become a GSoC mentor in 2014 where I have mentored to create Operation Theater Module for OpenMRS. Lukas was my first GSoC student who did a amazing job to successfully deliver the target functionality from the module. When my time permits, I always enjoying fixing JIRA tickets. At that time OpenMRS Guides program has initiated to help new comers to reduce their knowledge barrier and help them to quickly start the contributions to OpenMRS platform. With the time past, I became the leader of the program. We have a set of volunteers to help the new comers. We are currently helping new comers to reduce the learning curve and get started with OpenMRS quickly. We are able to get very good number of contributors to OpenMRS through this program and it's counting. FHIR which is the latest version of HL7 standard is another interested area for me. I was work with Suranga to create OpenMRS FHIR module to expose the OpenMRS domain objects through FHIR standard. It's a completely new solid standard which focus on provide better healthcare interoperability.  

This year, I again become a mentor in GSoC and I have mentored to create OAuth Module for the OpenMRS which can be use to provide the OAuth2 based security model for OpenMRS REST APIs. Mayank who is my GSoC student done a amazing work on that module to complete the required functionality. Glad to see his continuous contributions to OpenMRS platform where is a Release Manager for OpenMRS 2.0 release. 

With GSoC Student

The OpenMRS world wide summit has been a new type of event for OpenMRS. As I have already part of OpenMRS Implementers meeting and I know how valuable to take part in a OpenMRS event. In terms of getting details on the new projects going with OpenMRS and meet and share the thoughts with OpenMRS developers is always very important within these conferences. This time also I fortunate to meet almost all core developers and have a several chats on the current work carried out in the OpenMRS platform. I was fortunate to meet my GSoC student Mayank within the summit. It was really nice to meet, Paul, Burke, Darius, Downey, Mike, Daniel, Wyclif, Judy, Andrew, James, Kawesi and all other attendees during the summit. I have met Srimaurya in 2013 but never thought of seeing him again. But I had chance to meet him this time as well. I was closely working with Suranga but never had a chance to meet him. Finally I met him in Singapore even though he is near by my home in Sri Lanka. Dr. Niranjan also joined for the summit because of his interest through OpenMRS. We had a several discussions on how we going to adapt OpenMRS within Sri Lanka. I hope it was fruitful.

It was my first time in Singapore. It's really nice to be in Singapore and it'a amazing how much easy to travel all around the Singapore within short time with their advanced MRT system. I always enjoyed the night events organized during the summit days. Karaoke event was one of the best event. I enjoyed the BBQ night and the scenarios of that place. Obviously Marina Bay is one of the most attractive place in Singapore. Water show is simply amazing. It was really nice that I had a chance to explore the Singapore during the summit. 

During the summit, I mostly interested on Bahmini works, I attend several sessions which highlighted the capabilities of Bahmini. I was fortunate to deliver a lightening talk about FHIR which is a memorable experience for me. Last two days, I was participated in Hackthon. This time we divided into three set of groups and works on JIRA issues of projects. Our team mostly worked on REST module tickets. With out team effort and leadership of Stephan and support of Wyclif, we became the runners up. I got a special gift for the most contributed member and I was really happy. Gift was a power bank which I was looking to take a one. Thanks a lot for the gifts and wonderful trophy. We worked as a team to become runners up of the event and it was great experience for me to work with Wyclif, Mayank Stephan and few others(Sorry I don't remember all the names). 

After the Hackthon

Simply OpenMRS Worldwide Summit is one of best conference I have attended so far. Many thanks goes to Micheal and the events team to organize such a remarkable event. I'm really grateful for funding that I got from OpenMRS to attend this summit. It was always nice to be a member of OpenMRS community. Looking forward to meet you all in another wonderful event.  





Monday, November 30, 2015

Active Directory User Store Configurations for get LDAP users with their roles and role list WSO2 Servers

<?xml version="1.0" encoding="UTF-8"?>
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadOnlyLDAPUserStoreManager">
  <Property name="ConnectionName">user_wso2ldap</Property>
  <Property name="ConnectionURL">ldap://youdomain.com:389</Property>
  <Property encrypted="true" name="ConnectionPassword">######</Property>
  <Property name="UserSearchBase">CN=Users,DC=rm,DC=gr,DC=testypf,DC=com</Property>
  <Property name="UserNameListFilter">(objectClass=organizationalPerson)</Property>
  <Property name="UserNameAttribute">sAMAccountName</Property>
  <Property name="UserNameSearchFilter">(&amp;(objectClass=organizationalPerson)(sAMAccountName=?))</Property>
  <Property name="ReadOnly">true</Property>
  <Property name="MaxUserNameListLength">100</Property>
  <Property name="MaxRoleNameListLength">100</Property>
  <Property name="UserRolesCacheEnabled">true</Property>
  <Property name="SCIMEnabled">false</Property>
  <Property name="DisplayNameAttribute">sAMAccountName</Property>
  <Property name="Disabled">false</Property>
  <Property name="ReadGroups">false</Property>
  <Property name="GroupSearchBase">ou=system</Property>
  <Property name="GroupNameListFilter">(objectClass=groupOfNames)</Property>
  <Property name="GroupNameSearchFilter">(&amp;(objectClass=groupOfNames)(cn=?))</Property>
  <Property name="GroupNameAttribute">cn</Property>
  <Property name="MembershipAttribute">member</Property>
  <Property name="MemberOfAttribute">memberOf</Property>
  <Property name="MultiAttributeSeparator">,</Property>
  <Property name="PasswordHashMethod">PLAIN_TEXT</Property>
  <Property name="ReplaceEscapeCharactersAtUserLogin">true</Property>
  <Property name="ConnectionPoolingEnabled">false</Property>
  <Property name="UserDNPattern"/>
  <Property name="DomainName">TEST</Property>
  <Property name="Description"/>
</UserStoreManager>
NOTE : Depend on the User store structure, CN, DC and etc values may changed.

Sunday, November 15, 2015

Get User Store Domain of login user when user store domain not provided WSO2 APIs

Sometimes when we accessing APIs, there are situations when authenticated user again WSO2 not provided user store domain. But it's essential to get the which user store the user has authenticated. It can be a user in Primary Store or Secondary User Stores. UserCoreUtil class has following method which will gives you the domain that user has authenticated.


if (!username.contains(CarbonConstants.DOMAIN_SEPARATOR)) {
    String userStoreDomain = UserCoreUtil.getDomainFromThreadLocal();
    if (!StringUtils.isEmpty(userStoreDomain)) {
        username = UserCoreUtil.getDomainFromThreadLocal() + CarbonConstants.DOMAIN_SEPARATOR + username;
    }
}

Wednesday, November 11, 2015

Configuring Mutual SSL in WSO ESB Proxy Services and REST APIs

Configuring Mutual SSL in WSO ESB Proxy Services and REST APIs

What Mutual SSL?

Mutual authentication is the process where client authenticate with server and vice versa. With this approach client clients can be make sure that they are dealing business exclusively with trusted entities and from the server's perspective it can be certain that all would-be users are attempting to gain access for legitimate purposes.Two-way SSL authentication is one way of achieving the mutual SSL. During mutual SSL negotiation process, application acting as an SSL client presents its certificate to the SSL server after the SSL server authenticates itself to the SSL client

Mutual SSL for proxy service

  1. Edit https transportListener in axis2.xml  in {ESB_HOME}/repository/conf/axis2/ folder and Add SSLVerifyClient to optional as follow.

<transportReceiver name="https" class="org.apache.synapse.transport.passthru.PassThroughHttpSSLListener">
  <parameter name="port" locked="false">8243</parameter>
  <parameter name="non-blocking" locked="false">true</parameter>
  <parameter name="httpGetProcessor" locked="false">org.wso2.carbon.transport.nhttp.api.PassThroughNHttpGetProcessor</parameter>
  <parameter name="keystore" locked="false">
     <KeyStore>
        <Location>repository/resources/security/wso2carbon.jks</Location>
        <Type>JKS</Type>
        <Password>wso2carbon</Password>
        <KeyPassword>wso2carbon</KeyPassword>
     </KeyStore>
  </parameter>
  <parameter name="truststore" locked="false">
     <TrustStore>
        <Location>repository/resources/security/client-truststore.jks</Location>
        <Type>JKS</Type>
        <Password>wso2carbon</Password>
     </TrustStore>
  </parameter>
  <parameter name="SSLVerifyClient">optional</parameter>
  <!--supports optional|require or defaults to none -->
</transportReceiver>
  1. Next step is to enable the mutual SSL per proxy as it’s not required to all the proxies. In order to do that, create a local entry in ESB with following policy

<?xml version="1.0" encoding="UTF-8"?>
<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="MutualSSL">
  <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="true" />
                 </wsp:Policy>
              </sp:TransportToken>
              <sp:AlgorithmSuite>
                 <wsp:Policy>
                    <sp:Basic256 />
                 </wsp:Policy>
              </sp:AlgorithmSuite>
              <sp:Layout>
                 <wsp:Policy>
                    <sp:Lax />
                 </wsp:Policy>
              </sp:Layout>
           </wsp:Policy>
        </sp:TransportBinding>
        <rampart:RampartConfig xmlns:rampart="http://ws.apache.org/rampart/policy">
           <rampart:encryptionUser>useReqSigCert</rampart:encryptionUser>
           <rampart:timestampPrecisionInMilliseconds>true</rampart:timestampPrecisionInMilliseconds>
           <rampart:timestampTTL>300</rampart:timestampTTL>
           <rampart:timestampMaxSkew>300</rampart:timestampMaxSkew>
           <rampart:tokenStoreClass>org.wso2.carbon.security.util.SecurityTokenStore</rampart:tokenStoreClass>
           <rampart:nonceLifeTime>300</rampart:nonceLifeTime>
        </rampart:RampartConfig>
     </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

  1. Create a sample proxy service and configure the policy as follow.

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="Test" transports="https" statistics="disable" trace="disable" startOnLoad="true">
  <target>
     <inSequence>
        <log level="full" />
        <respond />
     </inSequence>
  </target>
  <enableSec />
  <policy key="MutualSSLPolicy" />
  <description />
</proxy>
4. After that it required to create a new client keystore and truststore which need to configured  in the client that communicate with the ESB. Follow below steps to setup the configurations. (This uses keytool commands to configure the keystore, trustore and certificates

  1. Create client keystore name client-keystore.jks

 keytool -genkey -keyalg RSA -keystore  client-keystore.jks -alias wso2clientkeystore -dname     "CN=wso2clientkeystore" -validity 3650 -keysize
2048

  1. Export the keystore certificate which will need to be imported for the trustores

keytool -export -keyalg RSA -keystore client-keystore.jks -alias wso2clientkeystore  -file wso2clientkeystore.cert
  1. Next step is to create the client side truststore where it stores the client certificates (public keys)
keytool -import -file wso2clientkeystore.cert -alias wso2client -keystore wso2clienttrustore.jks
  1. Now it’s required to import the ESB Server public certificate to client side truststore. First export the public key of the keystore of ESB in {ESB_HOME}//repository/resources/security/wso2carbon.jks as follow

keytool -export -keyalg RSA -keystore /repository/resources/security/wso2carbon.jks -alias wso2carbon -file wso2carbon.cert


  1. Above certificate need to be imported to client side truststore which is wso2clienttrustore.jks

keytool -import -file wso2carbon.cert -alias wso2carbon -keystore wso2clienttrustore.jks
  1. Import the client side certificate to ESB client truststore located in  the {ESB_HOME}//repository/resources/security/client-truststore.jks

keytool -import -file wso2clientkeystore.cert -alias wso2clientkeystore -keystore /repository/resources/security/client-truststore.jks
  1. With the above certificate configuration, it should be possible to access the proxy service with mutual SSL
  2. To test this, we can use SOAP UI
  3. First configure the keystore and truststore for the project pointing to client-keystore.jks and wso2clienttrustore.jks. Refer the below screenshot

ssl_keystore.png

  1. Then select the keystore as client-keystore.jks in properties. Refer below screenshot
invoke.png



  1. Then service should be able to execute successfully. But before it, following SOAP Fault should seen in the SOAP UI

beforeconfig.png

  1. Sample Mutul SSL SOAP client and REST Client can be found in [1] which written by Asela.

Mutual SSL for REST service

  1. Since certificates are already configured, following steps can be continue without configuring the certificates again.

  1. To configure Mutual SSL in a REST API in WSO2 ESB, it’s required to have a handler configured.
  2. In location [2], it can be found source for the handler which is a modified version of it’s original author Asela.
  3. It’s required to build the project. But location [3] contains already built jar(org.soasecurity.apim.authentication.handler-1.0.0.jar) which need to be deploy in {ESB_HOME}/repository/components/lib folder of ESB.
  4. Then create a API with following API definition


<?xml version="1.0" encoding="UTF-8"?>
<api context="/test" name="Test">
  <resource methods="GET" protocol="https" uri-template="/value/{tag}">
     <inSequence>
        <payloadFactory media-type="json">
           <format>{"Status":"OK"}</format>
           <args />
        </payloadFactory>
        <log>
           <property name="JSON-Payload" value="test" />
        </log>
        <property action="remove" name="NO_ENTITY_BODY" scope="axis2" />
        <property name="messageType" scope="axis2" type="STRING" value="application/json" />
        <respond />
     </inSequence>
  </resource>
  <handlers>
     <handler class="org.soasecurity.apim.authentication.handler.MutualSSLAuthenticationHandler" />
  </handlers>
</api>
  1. Above we have configured API with Mutual Authentication Handler which enforce the Mutual SSL authentication
  2. To test the API, it can be used the client in [1] or the modified client which adjust to prepare this sample in [4]
  3. With the client, API should be able to invoke successfully

Information sources taken mainly from [5] and [6] which are written by Asela and Hasitha.:)


[3] - https://svn.wso2.org/repos/wso2/people/harsha/mutual-ssl-hander/target/
[5] - http://tryitnw.blogspot.com.es/2015/06/setting-up-mutual-ssl-in-wso2-esb-and.html

[6] - http://xacmlinfo.org/2015/06/02/securing-apis-using-mutual-ssl-with-wso2-api-manager/