I am able to find similar question here on the site but not one specific that will help me fix my issue. I want to mask all but the last 4 digits of cardNo value coming in the request while Logging. Ex. if it is "cardNo":"10929291929312911131" then it should be logged as "cardNo":"XXXXXXXXXXXXXXXX1131. There can be two ways, cardNo is present in the request:
- "cardNo":"10929291929312911131"
- (cardNo:"10929291929312911131",cardType:"CREDIT")
Kindly, help me to correct my regex so that above patterns are captured.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.logging.log4j.core.*;
@Plugin(name = "LogMaskingConverter", category = "Convertor")
@ConvertorKeys({ "mask" })
public class LogMaskingConverter extend LogEventPatternConverter {
private static final Pattern SENSITIVE_DATA_PATTERN = Pattern.compile("(?<=\\bcardNo*)\\b*[0-9] {16}\\b");
private static final String REPLACEMENT_REGEX = "$1$2XXXXXXXXXXXXXXXX$3";
protected LogMaskingConverter(String name, String style) {
super(name, style);
}
public static LogMaskingConverter newInstance(String[] options) {
return new LogMaskingConverter("mask", Thread.currentThread().getName());
}
@Override
public void format(LogEvent event, StringBuilder outputMessage) {
String message = event.getMessage().getFormattedMessage();
String maskedMessage;
try {
maskedMessage = mask(message);
} catch (Exception e) {
maskedMessage = message;
}
outputMessage.append(maskedMessage);
}
private String mask(String message) {
StringBuffer buffer = new StringBuffer();
maskMatcher(SENSITIVE_DATA_PATTERN.matcher(message), buffer);
return buffer.toString();
}
private StringBuffer maskMatcher(Matcher matcher, StringBuffer buffer) {
while (matcher.find()) {
matcher.appendReplacement(buffer, REPLACEMENT_REGEX);
}
matcher.appendTail(buffer);
return buffer;
}
}
Edit 1:
There may or may not be space on either side of the colon. Could you please suggest: 1."cardNo" : "10929291929312911131" 2.creditCardData(cardNo: "10929291929312911131",cardType:"CREDIT") –
CodePudding user response:
Using Java, you might use a lookbehind with a finite quantifier asserting a certain amount of digits before matching the single digit to replace:
(?<=cardNo\"?\s?:\s?\"\d{0,100})\d(?!\d{0,3}\")
Explanation
(?<=
Positive lookahead, assert what is to the left iscardNo\"?\s?:\s?
MatchcardNo, optional
"`, optional whitespace char\"\d{0,100}
Match"
and for example 0-100 digits that can precede
)
Close the lookbehind\d
Match a single digit (which will be replaced byX
)(?!\d{0,3}\")
Negative lookahead, assert not 0-3 times a digit to the right followed by"
In the replacement use X
See a Regex demo and a Java demo