Search code examples
regexspring-bootlogbackembedded-jettyaccess-log

Request param is logged in access log with embedded jetty server of spring boot application


I have got an issue with my application, it logs request along with its query param which may contain sensitive data in access log. application is configured with logback.xml & embedded jetty.

jetty server is customized with below accessLogCustomer

public JettyServerCustomizer accessLogCustomizer() {
  return server -> {
    Slf4jRequestLog requestLog = new Slf4jRequestLog();
    requestLog.setExtended(true);
    requestLog.setLogLatency(true);
    requestLog.setPreferProxiedForAddress(true);
    requestLog.setLogTimeZone(userTimezone == null ? ZoneId.systemDefault().getId() : userTimezone);
    requestLog.setLogDateFormat("Y-MM-dd HH:mm:ss, SSS Z");

    RequestLogHandler requestLogHandler = new RequestLogHandler();
    requestLogHandler.setRequestLog(requestLog);
    requestLogHandler.setHandler(server.getHandler());
    server.setHandler(requestLogHandler);
  };
}

logback.xml

    <appender name="access" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>${logs.dir}/abc-access.log</File>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="ch.qos.logback.classic.PatternLayout">
                <Pattern>%m %n</Pattern>
            </layout>
            <charset>UTF-8</charset>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logs.dir}/abc-access.%d.log.gz</FileNamePattern>
        </rollingPolicy>
    </appender>
    <logger name="org.eclipse.jetty.server.RequestLog" additivity="false">
        <appender-ref ref="access"/>
    </logger>

request logged in access log

192.168.0.100 - - [2021-05-20 15:48:15,093 +0530] "POST /myAPI/v2/customer/message?myID=123&messageText=hello HTTP/1.0" 200 0 "-" "PostmanRuntime/7.26.8" 475

I am trying to avoid messageText from access log, but not getting any solution.


Solution

  • Use the CustomRequestLog and Slf4jRequestLogWriter instead.

    You'll want the special format option %U which emits the URL path, without the query string (which is available as %q btw)

    Your resulting configuration would look like this ...

    Slf4jRequestLogWriter slfjRequestLogWriter = new Slf4jRequestLogWriter();
    String format = "%{client}a - %u %t %m \"%U\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"";
    CustomRequestLog customRequestLog = new CustomRequestLog(slfjRequestLogWriter, format);
    server.setRequestLog(customRequestLog);
    

    Play with the format line, read the Javadoc on CustomRequestLog to know what you can do.

    Some notes:

    • The example format is not strictly following the Extended NCSA format (as it's missing the HTTP version portion, and the HTTP method is outside of the quoted section, but that is usually not a problem for many users)
    • Slf4jRequestLogWriter is only concerned with taking the formatted log line and sending it to the slf4j-api, it does nothing else.
    • RequestLogHandler is deprecated and not a recommended usage anymore (as it does not log bad requests and context-less requests), use the Server.setRequestLog(RequestLog) instead.

    Jetty will use the CustomRequestLog's Pattern to produce a String, this String is forwarded to the Slf4jRequestLogWriter as a slf4j logging event message, which is then logged per your existing slf4j + logback configuration.