Masking Sensitive Information using CXF Logging Interceptor

In this article we’ll see how to mask/hide sensitive information when using CXF Logging IN/OUT Interceptor.

The solution was built to run on Apache Karaf / Fuse ESB, but a similar approach can be utilised to run the custom logging interceptor on other environments.

package com.sachinhandiekar.cxf.logger;

import java.util.Arrays;
import java.util.List;

import org.apache.commons.lang.StringUtils;

public class SecureLoggingUtil {

    private String maskingChar;

    private String secureFields;

    private static final String REGEX_SPLIT = ",";

    private static final char SLASH = '/';

    public String maskSensitiveFields(String data) {
        List<String> sensitiveFieldsList = Arrays.asList(secureFields.trim()
                .split(REGEX_SPLIT));

        for (String sensitiveField : sensitiveFieldsList) {
            int beginIndex = 0;
            int lastIndex = -1;
            boolean emptyPass = false;

            while (beginIndex != -1
                    && (beginIndex = StringUtils.indexOfIgnoreCase(data, sensitiveField,
                            beginIndex)) > 0) {

                beginIndex = StringUtils.indexOf(data, ">", beginIndex);
                if (beginIndex != -1) {
                    char ch = data.charAt(beginIndex - 1);
                    if (ch == SLASH) {
                        emptyPass = true;
                    }
                    if (!emptyPass) {
                        lastIndex = StringUtils.indexOf(data, "<", beginIndex);
                        if (lastIndex != -1) {
                            String overlay = maskingChar;
                            String str2 = StringUtils.substring(data,
                                    beginIndex + 1, lastIndex);
                            if (str2 != null && str2.length() > 1) {
                                overlay = StringUtils.rightPad(overlay,
                                        str2.length(), maskingChar);

                                int temp = beginIndex + 1;
                                data = StringUtils.overlay(data, overlay, temp,
                                        lastIndex);
                            }
                        }
                    }
                    if (emptyPass) {
                        emptyPass = false;
                        lastIndex = beginIndex + 1;
                    } else {
                        if (lastIndex != -1) {
                            lastIndex = StringUtils
                                    .indexOf(data, ">", lastIndex);
                        }
                    }
                }
                beginIndex = lastIndex;
            }
        }
        return data;

    }

    public String getMaskingChar() {
        return maskingChar;
    }

    public void setMaskingChar(String maskingChar) {
        this.maskingChar = maskingChar;
    }

    public String getSecureFields() {
        return secureFields;
    }

    public void setSecureFields(String secureFields) {
        this.secureFields = secureFields;
    }

}
package com.sachinhandiekar.cxf.logger;

import org.apache.cxf.interceptor.LoggingInInterceptor;

/**
 * A simple logging handler which outputs the bytes of the message to the
 * Logger.
 */
public class SensitiveCXFLoggingInInterceptor extends LoggingInInterceptor {

    private boolean secureFieldStatus;

    private SecureLoggingUtil secureLoggingUtil;

    @Override
    protected String transform(String originalLogString) {

        if (secureFieldStatus) {
            return secureLoggingUtil.maskSensitiveFields(originalLogString);
        }

        return super.transform(originalLogString);
    }

    public SecureLoggingUtil getSecureLoggingUtil() {
        return secureLoggingUtil;
    }

    public void setSecureLoggingUtil(SecureLoggingUtil secureLoggingUtil) {
        this.secureLoggingUtil = secureLoggingUtil;
    }

    public boolean isSecureFieldStatus() {
        return secureFieldStatus;
    }

    public void setSecureFieldStatus(boolean secureFieldStatus) {
        this.secureFieldStatus = secureFieldStatus;
    }

}
package com.sachinhandiekar.cxf.logger;

import org.apache.cxf.interceptor.LoggingOutInterceptor;

public class SensitiveCXFLoggingOutInterceptor extends LoggingOutInterceptor {

    private boolean secureFieldStatus;

    private SecureLoggingUtil secureLoggingUtil;

    @Override
    protected String transform(String originalLogString) {

        if (secureFieldStatus) {
            return secureLoggingUtil.maskSensitiveFields(originalLogString);
        }

        return super.transform(originalLogString);
    }

    public SecureLoggingUtil getSecureLoggingUtil() {
        return secureLoggingUtil;
    }

    public void setSecureLoggingUtil(SecureLoggingUtil secureLoggingUtil) {
        this.secureLoggingUtil = secureLoggingUtil;
    }

    public boolean isSecureFieldStatus() {
        return secureFieldStatus;
    }

    public void setSecureFieldStatus(boolean secureFieldStatus) {
        this.secureFieldStatus = secureFieldStatus;
    }

}

Another approach using SOAP Payload - gist.github.com/sachin-handiekar/14b2ec8665..

Did you find this article valuable?

Support Sachin Handiekar by becoming a sponsor. Any amount is appreciated!