使用 logback 屏蔽 json 值
Mask json values using logback
我在 spring 引导项目的 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 日志消息中的敏感数据。我尝试了下面的方法来掩盖键“代码”的值。但是没用。
"msg": "%replace(%msg){'\"Code\":'.*'', '\"Code\":'xxx''}",
如何屏蔽 logstash appender 中的 json 值?
我能够通过编写 ValueMasker 的自定义实现来屏蔽敏感数据
需要两个组件:
- 实现
ValueMasker
的class
- 正在
logback.xml
中声明 jsonGeneratorDecorator
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", "random@email.com");
user.put("msg", "hello world");
JSONObject userDetails = new JSONObject(user);
logger.info("MaskingPatternExample log from {}" + userDetails);
}
}
{"msg":"MaskingPatternExample log from {}{\"email_id\":\"random@email.com\",\"msg\":\"xxxxxxxxxxx\",\"user_id\":\"97588\"}","log_type":"INFO"}
进一步documentation.
我在 spring 引导项目的 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 日志消息中的敏感数据。我尝试了下面的方法来掩盖键“代码”的值。但是没用。
"msg": "%replace(%msg){'\"Code\":'.*'', '\"Code\":'xxx''}",
如何屏蔽 logstash appender 中的 json 值?
我能够通过编写 ValueMasker 的自定义实现来屏蔽敏感数据
需要两个组件:
- 实现
ValueMasker
的class
- 正在
logback.xml
中声明
jsonGeneratorDecorator
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", "random@email.com");
user.put("msg", "hello world");
JSONObject userDetails = new JSONObject(user);
logger.info("MaskingPatternExample log from {}" + userDetails);
}
}
{"msg":"MaskingPatternExample log from {}{\"email_id\":\"random@email.com\",\"msg\":\"xxxxxxxxxxx\",\"user_id\":\"97588\"}","log_type":"INFO"}
进一步documentation.