'Encrypt a field in json log when using logstash logback encoder

In our scala apis we are using logstash-logback-encoder to create json logs. We want to encrypt a particular field. Masking is not enough as the value needs to be decrypted if need be from logs. What would be the best way to achieve this? One way could be to create an implementation of JsonGeneratorDecorator like there is one for masking. But given that we know which field to mask, is there an easier way to achieve this?


UPDATE : Solution

I used the suggestion provided by @Phil Clay in the answer. However, there was a small catch. The intention behind ValueMasker is to decide what/when to mask on the basis of values. For ex, using a RegEx to match against all values (net.logstash.logback.mask.RegexValueMasker). Because of their very generic usecase, ValueMaskers are less efficient/performant. However, my use case is more specific as there is a specific field to be masked. By definition FieldMasker should be used but it doesn't provide a handle to the value to allow encryption. In the end, I created a custom ValueMasker but used the logic from net.logstash.logback.mask.FieldNameBasedFieldMasker as below:

class FieldNameBasedEncryptionMasker extends ValueMasker {

  private var salt: String = ""
  private var fieldNames: Set[String] = Set.empty

  def addFieldName(fieldName: String): Unit =
    fieldNames = fieldNames + fieldName

  def setSalt(saltValue: String): Unit =
    salt = saltValue

  override def mask(context: JsonStreamContext, value: Any): AnyRef = {
    if (context.hasCurrentName && fieldNames.contains(context.getCurrentName) && value
          .isInstanceOf[CharSequence]) {
        // encrypt value  
    } else null
  }
}

This can be configured in `logback.xml as:

<appender name="stash" class="net.logstash.logback.appender.LogstashSocketAppender">
    <host>$host</host>
    <port>$port</port>
    <encoder class="net.logstash.logback.encoder.LogstashEncoder">
        <customFields>{"app_name":"${LOG_APP_NAME:-undefined}", "app_env":"${LOG_ENV:-local}"}</customFields>
        <jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
            <valueMasker class="FieldNameBasedEncryptionMasker">
                <salt>$logging-encryption-salt</salt>
                <fieldName>fieldNameToEncrypt1</fieldName>
                <fieldName>fieldNameToEncrypt2</fieldName>
            </valueMasker>
        </jsonGeneratorDecorator>
    </encoder>
</appender>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source