1

Below is my request body xml and I am making rest call with this request. Having custom LoggingInterceptor to log the request and response. I want to mask the user and password in logs.

<login><credentials user="user" Password="pass"/></login>

     private void traceRequest(final HttpRequest request, final byte[] body) throws IOException {
        logger.trace(
            String.format(
                "REQUEST uri=%s, method=%s, requestBody=%s",
                request.getURI(),
                request.getMethod(),
                new String(body, "UTF-8")));
    }

Currently I am printing my logs like below:

LoggingRequestInterceptor - REQUEST uri=http://localhost:8080/, method=POST, requestBody=<login><credentials user="user" Password="pass"/></login>

Below is my logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">

    <property name="logFile" value="logs/employee.log" />
    <property name="logFile-WS" value="logs/employee-ws.log" />


    <appender name="employee" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logFile}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logFile}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d [%thread] %-5level %logger{64} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="mainAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${logFile-WS}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${logFile-WS}.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d [%thread] %-5level %logger{64} - %replace(%msg){'having masking logic for other property'}%n</pattern>
        </encoder>
    </appender>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="org.springframework.ws.client.MessageTracing" level="TRACE" additivity="false">
        <appender-ref ref="mainAppender" />
    </logger>

    <logger name="org.springframework.ws.server.MessageTracing" level="TRACE" additivity="false">
        <appender-ref ref="mainAppender" />
    </logger>

    <logger name="com.employee.LoggingRequestInterceptor" level="TRACE" additivity="false">
        <appender-ref ref="mainAppender" />
    </logger>


    <root level="${root-log-level:-INFO}">
        <appender-ref ref="stdout"/>
        <appender-ref ref="mainAppender"/>
    </root>
</configuration>

Please someone help me to solve this. Note: I am using spring boot 2 and slf4j logger

Remo
  • 534
  • 7
  • 26

2 Answers2

2

Referring to Mask sensitive data in logs with logback

  1. Add logback-spring.xml in your project.
  2. Customize regular expression in the <patternsProperty> value to match the content your want to mask.
  3. Add the MaskingPatternLayout class (Use the updated one, the one in the beginning is not working) from the above answer

logback-spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="Console"
        class="ch.qos.logback.core.ConsoleAppender">
        <encoder
            class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="com.example.springboot.MaskingPatternLayout">
                <patternsProperty>(?:user|Password)="([a-zA-Z0-9]+)"
                </patternsProperty>
                <pattern>%d [%thread] %-5level %logger{35} - %msg%n</pattern>
            </layout>
        </encoder>
    </appender>

    <!-- LOG everything at INFO level -->
    <root level="info">
        <appender-ref ref="Console" />
    </root>
</configuration>

HelloController class to test


@RestController
public class HelloController {

    private static final Logger logger = LoggerFactory.getLogger(HelloController.class);

    @RequestMapping("/")
    public String index() {
        logger.info("<login><credentials user=\"user\" Password=\"pass\"/></login>");
        return "Greetings from Spring Boot!";
    }

}

Expected output


2020-04-13 12:38:47,511 [http-nio-8080-exec-1] INFO c.e.springboot.HelloController  - <login><credentials user="****" Password="****"/></login>

Update

  1. Please check if "console" should be "stdout"
<root level="${root-log-level:-INFO}">
    <appender-ref ref="console"/>
    <appender-ref ref="mainAppender"/>
</root>  

As no appender with name "console" is found.

  1. Suppose the logger is in LoggingRequestInterceptor, you need to add the "stdout" appender also.
<logger name="com.employee.LoggingRequestInterceptor"
    level="TRACE" additivity="false">
    <appender-ref ref="stdout" />
    <appender-ref ref="mainAppender" />
</logger>
samabcde
  • 6,988
  • 2
  • 25
  • 41
  • I have followed your answer. But still my logs are not masked. Also now logs are printing only in file. I want to log it in both console and file. – Remo Apr 13 '20 at 08:40
  • I have added logback xml in question and updated like (?:User|Password)="([a-zA-Z0-9]+)" %d [%thread] %-5level %logger{35} - %msg%n – Remo Apr 13 '20 at 08:47
  • yes it's stdout. I have updated and also after adding appender to LoggingRequestInterceptor, its not working for me – Remo Apr 13 '20 at 09:31
  • No log in console or no mask? – samabcde Apr 13 '20 at 09:32
  • both are not happening – Remo Apr 13 '20 at 09:33
  • Is there any other log in console, or only logs in file? In addition, in my project, I changed the main appender to start the server. I don't know if this is related. %d [%thread] %-5level %logger{64} - %replace(%msg){'having masking logic for other property',''}%n – samabcde Apr 13 '20 at 09:42
  • I have removed that existing logic pattern and tried. But not able to mask. usual logs are printing in files without masking. – Remo Apr 13 '20 at 09:55
  • Still no console log? The `MaskingPatternLayout` is only applied to console in your current configuration. You need to apply same update to the mainAppender for file log. Also the regex may need update as the user name and password may have other character. My example only mask alpha numeric value. – samabcde Apr 13 '20 at 10:00
  • no, still in console no logs printing. Also I have updated and tried the same in mainAppender. After adding it no logs printing in consloe and file – Remo Apr 13 '20 at 10:11
  • Can you give provide a dummy sample of user name and password? And can you try logging the message in my `HelloController` instead of the http response? I want to see if the log message make something wrong or the `MaskingPatternLayout` implementation has problem. – samabcde Apr 13 '20 at 10:17
  • dummy username="Test8_IN", Password="PojXcrQWKKJ" – Remo Apr 13 '20 at 10:23
  • Are you using the `MaskingPatternLayout` in the beginning of the answer? Use the updated one in the middle. – samabcde Apr 13 '20 at 10:32
  • yes my badness. I was not used the middle answer. Now updated and it's working for only alphanumeric. But my case have any values will be present. I just tried change your pattern like (.*). But it's printing as User=***********, not printing Password=******** – Remo Apr 13 '20 at 10:49
  • I suppose the user name and password has no ". Try (?:User|Password)="([^".]*)" – samabcde Apr 13 '20 at 10:56
0

I have added pattern with replace in logback.xml. It's masked user and password

<encoder>
            <pattern>%d [%thread] %-5level %logger{64} - %replace(  %replace(  %replace(%msg){'user="[^"]+"', 'user=*****'}  ){'Password="[^"]+"', 'Password=*****'}  ){'my another pattern', 'replacement'}%n</pattern>
</encoder>

Remo
  • 534
  • 7
  • 26