Logback (logstash-logback-encoder) での Mask の仕方

3 min read読了の目安(約2800字

メールアドレスなどの情報をログ出力の時にマスキングする際の方法のメモ

  • MaskingJsonGeneratorDecorator を使用する
    通常だと <valueMask> とかでやるのが良いのですが、中で使用している RegexValueMasker がうまく動かない[1]ので、自分で Masker を作成しました(Kotlin)。
EmailValueMasker.kt
package masker

import com.fasterxml.jackson.core.JsonStreamContext
import net.logstash.logback.mask.ValueMasker
import java.util.regex.Pattern

class EmailValueMasker : ValueMasker {
    companion object {
        val pattern = Pattern.compile("[a-zA-Z0-9]+[a-zA-Z0-9\\\\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\\\\._-]+", Pattern.DOTALL)
        const val mask = "*****@*****.***"
    }

    override fun mask(context: JsonStreamContext, value: Any?): Any? {
        val s = value as? String ?: return null
        val matcher = pattern.matcher(s)
        if (matcher.find()) {
            return matcher.replaceAll(mask)
        }
        return null
    }
}
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
      <jsonGeneratorDecorator class="net.logstash.logback.decorate.mask.MaskingJsonGeneratorDecorator">
	<valueMasker class="masker.EmailValueMasker">
	</pathMask>
      </jsonGeneratorDecorator>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="CONSOLE" />
  </root>
</configuration>
  • 出力する文字列を直接変更する
    単純に出力する文字列を logback の %replace を使用して置換しています。
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
      <providers>
        <timestamp />
        <version />
        <pattern>
          <omitEmptyFields>true</omitEmptyFields>
          <pattern>
            {
              "level": "%level",
              "message": "%replace(%msg){'[a-zA-Z0-9]+[a-zA-Z0-9\\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\\._-]+', '*****@***.***'}",
              "logger_name": "%logger",
              "thread_name": "%thread",
              "stack_trace": "%replace(%ex{full}){'[a-zA-Z0-9]+[a-zA-Z0-9\\._-]*@[a-zA-Z0-9_-]+[a-zA-Z0-9\\._-]+', '*****@***.***'}"
            }
          </pattern>
        </pattern>
      </providers>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="CONSOLE" />
  </root>
</configuration>
脚注
  1. stacktrace などの文字列も含めたいので改行が含むため Pattern.DOTALL を使用したい。 Matcher::matches を使用しているので全体 match するための正規表現が書くのが辛い。 ↩︎