Masking info before logging in Slf4G
package az.kapitalbank.integration.asanfinance.logging;
import com.fasterxml.jackson.core.JsonStreamContext;
import net.logstash.logback.mask.ValueMasker;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomLogFieldMasker implements ValueMasker {
private Pattern messagePattern;
private Pattern panPattern;
public void setMessageProperty(String messageProperty) {
this.messagePattern = buildPattern(messageProperty);
}
public void setPanProperty(String panProperty) {
this.panPattern = buildPattern(panProperty);
}
private Pattern buildPattern(String pattern) {
return StringUtils.isEmpty(pattern) ? null : Pattern.compile(pattern, Pattern.MULTILINE);
}
@Override
public Object mask(JsonStreamContext context, Object value) {
if (Objects.isNull(value)) {
return null;
}
if ("message".equals(context.getCurrentName())) {
StringBuilder message = new StringBuilder(value.toString());
replaceByPanProperty(message);
return replaceByPatternsProperty(message);
}
if ("pin".equals(context.getCurrentName())) {
return "******";
}
return null;
}
private void replaceByPanProperty(StringBuilder message) {
if (panPattern != null) {
Matcher matcher = panPattern.matcher(message);
while (matcher.find()) {
if (matcher.group(0) != null) {
for (int i = matcher.start(0) + 6; i < matcher.end(0) - 4; i++) {
message.setCharAt(i, '*');
}
}
}
}
}
private String replaceByPatternsProperty(StringBuilder message) {
if (messagePattern != null) {
Matcher matcher = messagePattern.matcher(message);
while (matcher.find()) {
int groupIndex = 1;
while (groupIndex <= matcher.groupCount()) {
if (matcher.group(groupIndex) != null) {
int start = matcher.start(groupIndex);
int end = matcher.end(groupIndex);
if ((end - start) > 1) {
for (int i = start + 1; i < end; i++) {
message.setCharAt(i, '*');
}
}
}
groupIndex++;
}
}
}
return message.toString();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="CONSOLE_JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>false</includeContext>
<includeCallerData>true</includeCallerData>
<fieldNames>
<timestamp>timestamp</timestamp>
<message>message</message>
<logger>[ignore]</logger>
<version>[ignore]</version>
<levelValue>[ignore]</levelValue>
<caller>trace</caller>
<stackTrace>exception</stackTrace>
<mdc>context</mdc>
</fieldNames>
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="az.kapitalbank.integration.asanfinance.logging.CustomLogFieldMasker">
<panProperty>\b\d{16,19}\b</panProperty>
<messageProperty>
pin\s*(=|:)?\s*([^,\)]+)
</messageProperty>
</valueMasker>
</jsonGeneratorDecorator>
</encoder>
</appender>
<springProfile name="!prod">
<logger name="az.kapitalbank.adapter" level="DEBUG"/>
<root level="WARN">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="prod">
<logger name="az.kapitalbank.adapter" level="INFO"/>
<root level="WARN">
<appender-ref ref="CONSOLE_JSON"/>
</root>
</springProfile>
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
</configuration>
EMAIL MASKER:
package az.kapitalbank.commons.stmtreporthandler.logging;
import com.fasterxml.jackson.core.JsonStreamContext;
import net.logstash.logback.mask.ValueMasker;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomLogFieldMasker implements ValueMasker {
private Pattern emailPattern;
public void setEmailProperty(String emailProperty) {
this.emailPattern = buildPattern(emailProperty);
}
private Pattern buildPattern(String pattern) {
return StringUtils.isEmpty(pattern) ? null : Pattern.compile(pattern, Pattern.MULTILINE);
}
@Override
public Object mask(JsonStreamContext context, Object value) {
if (Objects.isNull(value)) {
return null;
}
if ("message".equals(context.getCurrentName())) {
StringBuilder message = new StringBuilder(value.toString());
replaceByEmailProperty(message);
return message.toString();
}
if ("mail".equals(context.getCurrentName()) || "to".equals(context.getCurrentName())) {
return maskEmail(value.toString());
}
return null;
}
private void replaceByEmailProperty(StringBuilder message) {
if (emailPattern != null) {
Matcher matcher = emailPattern.matcher(message);
while (matcher.find()) {
String maskedEmail = maskEmail(matcher.group(0));
message.replace(matcher.start(), matcher.end(), maskedEmail);
}
}
}
private String maskEmail(String email) {
Matcher matcher = emailPattern.matcher(email);
if (matcher.matches()) {
String firstChar = matcher.group(1); // Первый символ
String lastChar = matcher.group(3); // Последний символ перед @
String domain = matcher.group(4); // Домен (оставляем как есть)
return firstChar + "********" + lastChar + "@" + domain;
}
return email;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<appender name="CONSOLE_JSON" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<includeContext>false</includeContext>
<includeCallerData>true</includeCallerData>
<fieldNames>
<timestamp>timestamp</timestamp>
<message>message</message>
<logger>[ignore]</logger>
<version>[ignore]</version>
<levelValue>[ignore]</levelValue>
<caller>trace</caller>
<stackTrace>exception</stackTrace>
<mdc>context</mdc>
</fieldNames>
<jsonGeneratorDecorator class="net.logstash.logback.mask.MaskingJsonGeneratorDecorator">
<valueMasker class="az.kapitalbank.commons.stmtreporthandler.logging.CustomLogFieldMasker">
<emailProperty>
\b([a-zA-Z0-9])([a-zA-Z0-9._%+-]*)([a-zA-Z0-9])@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})\b
</emailProperty>
</valueMasker>
</jsonGeneratorDecorator>
</encoder>
</appender>
<springProfile name="!prod">
<logger name="az.kapitalbank.atlas" level="DEBUG"/>
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="prod">
<logger name="az.kapitalbank.atlas" level="INFO"/>
<root level="INFO">
<appender-ref ref="CONSOLE_JSON"/>
</root>
</springProfile>
<shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
</configuration>
package az.kapitalbank.commons.stmtreporthandler.dto;
import az.kapitalbank.commons.stmtreporthandler.client.model.cardstatement.Direction;
import az.kapitalbank.commons.stmtreporthandler.client.model.cardstatement.Sort;
import az.kapitalbank.commons.stmtreporthandler.client.model.cardstatement.StatementFilter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class StatementRequestReceiverDto {
@JsonIgnore
private String id;
private String pan;
private String cardUID;
private String accountNumber;
private FileType fileType;
private List<NotificationType> notificationTypes;
private LocalDateTime fromDate;
private LocalDateTime toDate;
private MailDto mail;
private ReportLang lang;
public StatementFilter statementFilter(Integer limit) {
return StatementFilter.statementBuilder()
.id(id)
.accountNumber(accountNumber)
.fromDate(fromDate)
.toDate(toDate)
.cardUID(cardUID)
.pan(pan)
.sort(Sort.DESC)
.direction(Direction.BOTH)
.limit(limit)
.build();
}
}
package az.kapitalbank.commons.stmtreporthandler.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
public class MailDto extends BaseNotificationParams {
private String to;
}
Комментарии
Отправить комментарий