Home > Enterprise >  Java regex to mask a value in a string having a fixed pattern
Java regex to mask a value in a string having a fixed pattern

Time:03-24

I have different types of logs having a common pattern. What I intend to do is mask the value present in it with #.

cvc-length-valid: Value '9899488103' with length = '10' is not facet-valid with respect to length '20' for type 'customerId'.

cvc-pattern-valid: Value 'GB200102BUYFNBUYSN' is not facet-valid with respect to pattern '[A-Za-z]{2,2}(17|18|19|20|21)[0-9]{2}((0)[1-9]|(1)[012])((0)[1-9]|(1|2)[0-9]|(3)[01])[A-Za-z]{1}[A-Za-z#]{4}[A-Za-z]{1}[A-Za-z#]{4}' for type '#AnonType_NATIONAL_ID_CONCATbuyerSellerId'.

Expected Output

cvc-length-valid: Value '#####' with length = '10' is not facet-valid with respect to length '20' for type 'customerId'.
cvc-pattern-valid: Value '#####' is not facet-valid with respect to pattern '[A-Za-z]{2,2}(17|18|19|20|21)[0-9]{2}((0)[1-9]|(1)[012])((0)[1-9]|(1|2)[0-9]|(3)[01])[A-Za-z]{1}[A-Za-z#]{4}[A-Za-z]{1}[A-Za-z#]{4}' for type '#AnonType_NATIONAL_ID_CONCATbuyerSellerId'.

CodePudding user response:

You could try a regex replacement:

String input = "cvc-length-valid: Value '9899488103' with length = '10' is not facet-valid with respect to length '20' for type 'customerId'.";
String output = input.replaceAll("(\\S ): Value '.*?' (.*)", "$1: Value '#####' $2");
System.out.println(output);

This prints:

cvc-length-valid: Value '#####' with length = '10' is not facet-valid with respect to length '20' for type 'customerId'.

CodePudding user response:

One practice is to use LayoutWrappingEncoder and configuration class to read the masking patterns from the configuration and apply them in the log messages. This is rather a simple approach and can be achieved with a custom pattern handler.

The MaskingPatternLayout (Configuration) class to read patterns

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()) {
            IntStream.rangeClosed(1, matcher.groupCount()).forEach(group -> {
                if (matcher.group(group) != null) {
                    IntStream.range(matcher.start(group), matcher.end(group)).forEach(i -> sb.setCharAt(i, '#'));
                }
            });
        }
        return sb.toString();
    }
}

And pattern matcher(here i assumed we using Logback as log provider) as logback.xml file .

<configuration>
    <appender name="mask" >
        <encoder >
           <layout >
           <maskPattern>\"YOU mentioned log pattern\"</maskPattern>
         
            </layout>
        </encoder>
    </appender>
</ configuration>
  • Related