I am working with logback with springboot project first time; and I have tried to look references online. I am dealing with masking sensitive data on different log files. In this project data is coming from different api endpoints within the same module; I also have different json responses and requests that have data that need masking. I have provided example below.
ACCOUNT module
/account/member/list
{ "name": "Apple", "email": "[email protected]", "address": "Elem 4324 5684 USA" }/account/payment/history
{
"first": "Apple",
"last": "Large",
"cardNum": "444444444444"
}
The masking logic on my logback file looks as follows, and I having two separate log files for the above
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
.......
.......
<appender name="MEMBER"
----
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.fedex.srs.cpg.paymentvalidationapi.filter.MaskingPatternLayout">
<maskPattern>\"email\"\s*:\s*\"(.*?)\"</maskPattern>
<maskPattern>\"address\"\s*:\s*\"(.*?)\"</maskPattern>
<maskPattern>\"cardNum\"\s*:\s*\"([0-9]{14,16})\"</maskPattern>
---10 more similar patterns
</layout>
</encoder>
.......
.......
</appender>
<appender name="PAYMENT"
----
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="com.fedex.srs.cpg.paymentvalidationapi.filter.MaskingPatternLayout">
<maskPattern>\"email\"\s*:\s*\"(.*?)\"</maskPattern>
<maskPattern>\"address\"\s*:\s*\"(.*?)\"</maskPattern>
<maskPattern>\"cardNum\"\s*:\s*\"([0-9]{14,16})\"</maskPattern>
---10 more similar patterns
</layout>
</encoder>
.......
.......
</appender>
</configuration>
Above encoder repeated for each appender, and I am only showing two here but I have 6 log files. I repeated Masking layout because the order of the maskPattern important for my MaskingPatternLayout class to work I created the class based on baeldung tutorial
public class MaskingPatternLayout extends PatternLayout {
private Pattern multilinePattern;
private List<String> maskPatterns = new ArrayList<>();
public void addMaskPattern(String maskPattern) {
maskPatterns.add(maskPattern);
multilinePattern = Pattern.compile(maskPatterns.stream().collect(Collectors.joining("|")), Pattern.MULTILINE);
}
@Override
public String doLayout(ILoggingEvent event) {
return maskMessage(super.doLayout(event));
}
private String maskMessage(String message) {
if (multilinePattern == null) {
return message;
}
StringBuilder sb = new StringBuilder(message);
Matcher matcher = multilinePattern.matcher(sb);
while (matcher.find()) {
for (int groupIndex = 1; groupIndex <= matcher.groupCount(); groupIndex++)
if (matcher.group(groupIndex) != null) {// b.subSequence(st, end) != null
int st = matcher.start(groupIndex);
int end = matcher.end(groupIndex);
//each case represent each maskPattern on the logback.xml file
switch (groupIndex) {
case 1:// email
case 2:// address
//mask everything
break;
case 3:// cardNum
//I have logic to leave last four characters unmasked
break;
.......
........
default:
break;
}
}
}
return sb.toString();
}
}
The logback xml maskPattern order is tightly coupled with the MaskingPatternLayout class switch statement. My question: Is there a better way of handling this or is my current approach has cost performance wise? If I have ten patterns only one pattern is associated with one log file, I am still running 9 of those patterns against this one particular file. Is that correct? In above if I am logging payment information, my logback still running the email and address patterns against the payment log message; if I understand things correctly. Since it is springboot project, is autowiring Masking class helps for performance? Maybe I did not understand how things are wired. I need advice on how to approach this. Is the current approach something I can use in production environment?