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......

No comments:

Post a Comment

Blogger Widgets