Tuesday, January 31, 2017

Data Masking using class mediator in WSO2 ESB

If you are looking for an easy way to mask a sensitive information in the soap body inside the WSO2 ESB, then this would be the best option. You can go for a class mediator to achieve your requirement and please follow below steps in oder to achieve .

Step1

Create a mediator project and add following dependencies to pom file.


<dependencies>
   <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.21</version>
   </dependency>
   <dependency>
      <groupId>org.json.wso2</groupId>
      <artifactId>json</artifactId>
      <version>2.0.0.wso2v1</version>
   </dependency>
</dependencies>

Step 2

After modifying the pom file if those libraries available to import in java code, go to mediator project root directory from and run below command


mvn eclipse:eclipse

Step 3

Add following code to your class.


package com.sachini.sample;


import org.apache.synapse.MessageContext;

import org.apache.synapse.mediators.AbstractMediator;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;


public class DatamaskMediator extends AbstractMediator {


    private static final Logger LOGGER = LoggerFactory

            .getLogger(DatamaskMediator.class);


    public boolean mediate(MessageContext context)


    {

        JSONObject jsonObject = maskJsonPayload(context);

        context.setProperty("MASKED_PAYLOAD", jsonObject.toString());

        return true;

    }


    public JSONObject maskJsonPayload(MessageContext messageContext) {

        // extract properties

        String maskingKeys = (String) messageContext

                .getProperty("MASKING_KEYS");

        String stringPayload = (String) messageContext

                .getProperty("TARGET_PAYLOAD");


        JSONArray keys;

        try {

            keys = new JSONObject(maskingKeys).getJSONArray("keysToBeMasked");

        } catch (JSONException e) {

            LOGGER.error("Error parsing masking key array. > " + e.toString());

            return null;

        }

        JSONObject jsonPayload;

        try {

            jsonPayload = new JSONObject(stringPayload);

        } catch (JSONException e) {

            LOGGER.error("Error parsing Json payload. recived payload is : "

                    + messageContext.getProperty("TARGET_PAYLOAD"));

            return null;

        }

        maskJsonPayload(jsonPayload, keys);

        return jsonPayload;


    }


    public void maskJsonPayload(JSONObject jsonPayload, JSONArray keys) {


        // String contexts=null;

        JSONArray innerArray = null;

        JSONArray replacementArray = null;

        String lastContext = null;

        String contexts[] = null;

        JSONObject tmpJsonObject = jsonPayload;

        for (int k = 0; k < keys.length(); k++) {


            try {

                contexts = keys.getString(k).split("\\.");

            } catch (JSONException e) {

                LOGGER.error("Error parsing Keys. May be in invalid format");

            }

            lastContext = contexts[contexts.length - 1];

            for (String context : contexts) {


                if (!jsonPayload.has(context)) {

                    break;

                } else if (jsonPayload.optJSONObject(context) != null) {

                    if (context.equals(lastContext)) {

                        // this mean entire onject to be masked.

                        JSONObject tmpJson = new JSONObject();

                        try {

                            tmpJson.put("********", "************");

                            jsonPayload.put(context, tmpJson);

                        } catch (JSONException e) {

                            LOGGER.error("Error replace data with mask value :"

                                    + e.getMessage());

                            return;

                        }

                        break;

                    } else {


                        try {

                            jsonPayload = jsonPayload.getJSONObject(context);

                        } catch (JSONException e) {

                            LOGGER.error("Error parsing Json payload.");

                            return;

                        }

                        continue;

                    }

                } else if (jsonPayload.optJSONArray(context) != null) {

                    try {

                        innerArray = jsonPayload.getJSONArray(context);


                        replacementArray = new JSONArray();

                        for (int i = 0; i < innerArray.length(); i++) {

                            replacementArray.put("************");

                        }


                        jsonPayload.put(context, replacementArray);

                    } catch (JSONException e) {

                        LOGGER.error("Error replace data with mask value :"

                                + e.getMessage());

                        return;

                    }

                    break;

                } else {

                    try {

                        jsonPayload.put(context, "************");

                    } catch (JSONException e) {

                        LOGGER.error("Error replace data with mask value :"

                                + e.getMessage());

                        return;

                    }

                    break;

                }


            }

            // toupdate the this cycle results to next iteration

            jsonPayload = tmpJsonObject;

        }

        return;


    }

}

Step 5

Create an api to call the above sequence.


<api xmlns="http://ws.apache.org/ns/synapse" name="sampleAPI" context="/sampleAPI">
   <resource methods="POST GET" inSequence="dataMaskerSeq"/>
</api>

Step 6

Add this keysToBeMask.json to the registry path (/_system/governance/custom/keysToBeMasked.json) which is referred in your sequence. From this json file we are defining what will be the fields we need to mask from the payload.

keysToBeMask.json


<api xmlns="http://ws.apache.org/ns/synapse" name="sampleAPI" context="/sampleAPI">
   <resource methods="POST GET" inSequence="dataMaskerSeq"/>
</api>

Step 7

Send the request to api as following.

<account>
   <name>Borella</name>
   <password>12345</password>
   <active>yes</active>
   <code>sacfiles</code>
</account>

Then you will get a response like this.

<account>
   <name>Borella</name>
   <password>*****</password>
   <active>yes</active>
   <code>*****</code>
</account>

Thanks and have a nice day......

Monday, January 16, 2017

How to add external jar libraries to the Carbon Application Project in WSO2

WSO2 Carbon is a componentized Service Oriented Platform(SOA) platform which is build on top OSGi. Since WSO2 Carbon is based on OSGi, you can only extend the platform by dropping OSGi bundles.

The OSGi repository of WSO2 Carbon is located inside the $CARBON_HOME/repository/components folder. $CARBON_HOME is the folder where you extracted an Carbon or Carbon based product. 

You can use following directories to drop external user libraries. But you need to restart the server after adding libraries.

$CARBON_HOME/repository/components/dropins

This is the place where you can drop OSGi bundles.

$CARBON_HOME/repository/components/lib

The jar files you drop into this folder will be converted to OSGi bundles during the next server startup.

So if you want to hot deploy your custom jar files without adding to $CARBON_HOME/repository/components/lib as mentioned, you can use Java Library Project and follow below steps in WSO2 Developer Studio.

Java Library Project

With Java Library Project, you can refer a jar file or a project in your workspace and make it a bundle which will be available in to bundle classpath during the runtime. 

1) Create a Java Library Project, open WSO2 Developer Studio Dashboard and select Java Library Project from Carbon category


2) Provide a project name and click Next, Then you will navigate to a screen where you have to add your artifact.

There are two ways to create a Java Library Artifact.

  • From File System
  • From Workspace
In here we go for "File System" option, since we assume that we do have the custom jar created in our file system.

3) Upload your custom jar and click Finish.

4) Then create Carbon Application Project,  add the created Library Project to it and make a Carbon Application Archive out of it. (Make sure to set the Server Role to "Enterprise Service Bus" for Library Project)

5) Upload the .CAR to ESB server, then you will be able to see following log for successful deployment of the custom jar file.



[2017-01-17 10:25:01,731]  INFO - ApplicationManager Deploying Carbon Application : DISCOVERY_1.0.0.car...
[2017-01-17 10:25:02,710]  INFO - DefaultAppDeployer OSGi bundle in file:///home/sachini/Documents/Projects/DISCOVERY/wso2esb-5.0.0/tmp/carbonapps/-1234/1484628901732DISCOVERY_1.0.0.car/JavaLibProject_1.0.0/JavaLibProject-1.0.0.jar location is about to be installed to Carbon Server.
[2017-01-17 10:25:02,712]  INFO - DefaultAppDeployer OSGi bundle JavaLibProject installed to Carbon Server.
[2017-01-17 10:25:02,718]  INFO - DefaultAppDeployer OSGi bundle JavaLibProject successfully started on Carbon Server.

So from this, you don't need to add the .jar manually to lib folder. You can add all your synapse configurations (proxy,api etc) along with the dependent custom jars to a single .car and deploy it in ESB server at run time.

Thanks...
Blogger Widgets