使用 logback 屏蔽 json 值

问题描述 投票:0回答:2

我在我的 Spring Boot 项目的 logback 配置中使用下面的 Logstash 编码器。

<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
        <providers>
            <pattern>
                <pattern>
                    {
                        "creation_timestamp": "%d{yyyy-MM-dd'T'HH:mm:ss, UTC}",
                        "msg": "%msg",
                        "log_type": "%level",
                     }   
                </pattern>
                <omitEmptyFields>true</omitEmptyFields>
            </pattern>
        </providers>
    </encoder>

我想屏蔽 json 日志消息中的敏感数据。我尝试了以下方法来掩盖键“Code”的值。但这不起作用。

"msg": "%replace(%msg){'\"Code\":'.*'', '\"Code\":'xxx''}",

如何在 Logstash 附加程序中屏蔽 json 值?

java logging logback logstash-logback-encoder
2个回答
1
投票

我能够通过编写 ValueMasker 的自定义实现来屏蔽敏感数据

需要两个组件:

  1. 实现
    ValueMasker
  2. 的类
  3. 在您的
    jsonGeneratorDecorator
     中声明 
    logback.xml
package com.mask;

import com.fasterxml.jackson.core.JsonStreamContext;
import net.logstash.logback.mask.ValueMasker;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

public class SensitiveMaskingPatternLayout implements ValueMasker {
    private Pattern multilinePattern = Pattern.compile("\\\"msg\\\"\\s*:\\s*\\\"(.*?)\\\"", Pattern.MULTILINE);;
    private List<String> maskPatterns = new ArrayList<>();

    private String maskMessage(String 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, 'x'));
                }
            });
        }
        return sb.toString();
    }

    @Override
    public Object mask(JsonStreamContext context, Object value) {
        if (value instanceof CharSequence) {
            return maskMessage((String) value);
        }
        return value;
    }
}

<configuration>

    <appender name="mask" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
            <providers>
                <pattern>
                    <pattern>
                        {
                            "msg": "%msg",
                            "log_type": "%level"
                        }
                    </pattern>
                    <omitEmptyFields>true</omitEmptyFields>
                </pattern>
            </providers>
            <logLevel>
                INFO
            </logLevel>
            <jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
                <valueMasker class="com.mask.SensitiveMaskingPatternLayout"/>
            </jsonGeneratorDecorator>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="mask" />
    </root>

</configuration>

示例:

package com.example;

import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {

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

    public static void main(String[] args) {
        Map<String, String> user = new HashMap<>();
        user.put("user_id", "97588");
        user.put("email_id", "[email protected]");
        user.put("msg", "hello world");
        JSONObject userDetails = new JSONObject(user);

        logger.info("MaskingPatternExample log from {}" + userDetails);
    }

}

{"msg":"MaskingPatternExample log from {}{\"email_id\":\"[email protected]\",\"msg\":\"xxxxxxxxxxx\",\"user_id\":\"97588\"}","log_type":"INFO"}

更多文档


0
投票

ValueMasker
方法对我不起作用。如果您遇到同样的问题,这就是有效的方法:

  1. 如果您注意到

    LoggingEventCompositeJsonEncoder
    中的
    logback.xml
    ,它有这些名为
    <providers>
    的字段。

  2. 进一步检查,你会发现这些

    LoggingEventJsonProviders
    基本上设置了我们编码器中的所有json字段。

  3. 因此,如果你有一个名为

    <message>
    的字段,它是一个提供者,你可以通过扩展
    AbstractFieldJsonProvider
    类来修改该字段的内容,如下所示:

    public class ModifyingProvider extends AbstractFieldJsonProvider < ILoggingEvent > {
    private final Pattern[] maskPatterns;
    public ModifyingProvider() {
      maskPatterns = new Pattern[] {
        Pattern.compile("\\b[0-9]{2}-[0-9]{2}-[0-9]{4}\\b"), // DOB pattern (DD-MM-YYYY)
          // Add more patterns as needed
      };
    }
    private String maskData(String message) {
      StringBuilder maskedMessage = new StringBuilder(message);
    
      for (Pattern pattern: maskPatterns) {
        Matcher matcher = pattern.matcher(maskedMessage);
    
        while (matcher.find()) {
          String match = matcher.group();
          String maskedValue = mask(match);
          maskedMessage.replace(matcher.start(), matcher.end(), maskedValue);
        }
      }
    
      return maskedMessage.toString();
    }
    private String mask(String originalValue) {
      // Masking Logic
    }
    
    @Override
    public void writeTo(JsonGenerator generator, ILoggingEvent event) throws IOException {
      // Modify the log message or provide an alternative message here
    
      String modifiedMessage = modifyMessage(originalMessage);
    
      // Write the modified message to the JSON output
      generator.writeStringField("message", modifiedMessage);
    }
    
    private String modifyMessage(String originalMessage) {
      return maskData(originalMessage);
    }
    
  4. 然后在您的

    logback.xml
    中,只需替换所需的
    <provider>
    标签,或者在本例中将
    <message>
    标签替换为
    <provider class="path.to.your.class.ModifyingProvider"/>

© www.soinside.com 2019 - 2024. All rights reserved.