Skip to content

Commit 3f29c8e

Browse files
author
Jonathan Henrique Medeiros
committed
upgrade spring version and added logging obfuscator configuration for sensitive field values
1 parent 4d26d28 commit 3f29c8e

File tree

8 files changed

+115
-11
lines changed

8 files changed

+115
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Esta arquitetura consiste em diminuir a concorrência entre transações da API
1717
</br>
1818

1919
[![node](https://img.shields.io/badge/Azul_Zulu_OpenJDK-21-red.svg)](https://www.azul.com/downloads/?package=jdk#zulu)
20-
[![node](https://img.shields.io/badge/Spring_Boot-3.3.0-green.svg)](https://spring.io/)
20+
[![node](https://img.shields.io/badge/Spring_Boot-3.4.0-green.svg)](https://spring.io/)
2121
[![node](https://img.shields.io/badge/MySQL-8.0.28-blue.svg)](https://www.mysql.com/)
2222

2323

pom.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<parent>
66
<groupId>org.springframework.boot</groupId>
77
<artifactId>spring-boot-starter-parent</artifactId>
8-
<version>3.3.3</version>
8+
<version>3.4.0</version>
99
<relativePath/>
1010
</parent>
1111

@@ -106,6 +106,10 @@
106106
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
107107
<version>${springdoc-openapi-starter-webmvc-ui.version}</version>
108108
</dependency>
109+
<dependency>
110+
<groupId>io.opentelemetry</groupId>
111+
<artifactId>opentelemetry-api</artifactId>
112+
</dependency>
109113
<dependency>
110114
<groupId>com.h2database</groupId>
111115
<artifactId>h2</artifactId>
@@ -116,10 +120,6 @@
116120
<artifactId>spring-boot-starter-test</artifactId>
117121
<scope>test</scope>
118122
</dependency>
119-
<dependency>
120-
<groupId>io.opentelemetry</groupId>
121-
<artifactId>opentelemetry-api</artifactId>
122-
</dependency>
123123
</dependencies>
124124

125125
<build>
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package br.com.multidatasources.config.logging;
2+
3+
import ch.qos.logback.classic.spi.ILoggingEvent;
4+
import ch.qos.logback.core.pattern.CompositeConverter;
5+
6+
import java.io.BufferedReader;
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.io.InputStreamReader;
10+
import java.util.Collections;
11+
import java.util.HashMap;
12+
import java.util.List;
13+
import java.util.Map;
14+
import java.util.regex.Matcher;
15+
import java.util.regex.Pattern;
16+
17+
public class ObfuscateLoggingConverter extends CompositeConverter<ILoggingEvent> {
18+
19+
private static final Map<String, Pattern> sensitiveFieldPatterns = new HashMap<>();
20+
private static final int GROUP_FIELD_IN_MESSAGE_INDEX = 1;
21+
private static final int GROUP_FIELD_IN_JSON_INDEX = 2;
22+
23+
static {
24+
final List<String> fieldNames = getAllSensitiveFieldNames();
25+
for (final String fieldName : fieldNames) {
26+
final String regex = "(?i)\\b" + Pattern.quote(fieldName) + "\\b\\s*[:=]\\s*\"?([^\",\\s]*)\"?|\"" + Pattern.quote(fieldName) + "\":\"([^\"]*)\"";
27+
sensitiveFieldPatterns.put(fieldName, Pattern.compile(regex));
28+
}
29+
}
30+
31+
@Override
32+
protected String transform(final ILoggingEvent event, final String in) {
33+
String message = in;
34+
for (Map.Entry<String, Pattern> entry : sensitiveFieldPatterns.entrySet()) {
35+
message = obfuscateFieldValue(message, entry.getValue());
36+
}
37+
message = obfuscateArguments(event.getArgumentArray(), message);
38+
message = obfuscateMDC(event.getMDCPropertyMap(), message);
39+
return message.concat("\n");
40+
}
41+
42+
private static String obfuscateFieldValue(final String message, final Pattern pattern) {
43+
final Matcher matcher = pattern.matcher(message);
44+
final StringBuilder sb = new StringBuilder();
45+
while (matcher.find()) {
46+
if (matcher.group(GROUP_FIELD_IN_MESSAGE_INDEX) != null) {
47+
matcher.appendReplacement(sb, matcher.group().replace(matcher.group(GROUP_FIELD_IN_MESSAGE_INDEX), "****"));
48+
}
49+
if (matcher.group(GROUP_FIELD_IN_JSON_INDEX) != null) {
50+
matcher.appendReplacement(sb, matcher.group().replace(matcher.group(GROUP_FIELD_IN_JSON_INDEX), "****"));
51+
}
52+
}
53+
matcher.appendTail(sb);
54+
return sb.toString();
55+
}
56+
57+
private static String obfuscateArguments(final Object[] arguments, String message) {
58+
if (arguments != null) {
59+
for (final Object arg : arguments) {
60+
if (arg != null) {
61+
for (final Pattern pattern : sensitiveFieldPatterns.values()) {
62+
message = obfuscateFieldValue(message, pattern);
63+
}
64+
}
65+
}
66+
}
67+
return message;
68+
}
69+
70+
private static String obfuscateMDC(final Map<String, String> mdcPropertyMap, String message) {
71+
if (mdcPropertyMap != null) {
72+
for (final Map.Entry<String, String> entry : mdcPropertyMap.entrySet()) {
73+
if (sensitiveFieldPatterns.containsKey(entry.getKey())) {
74+
message = obfuscateFieldValue(message, sensitiveFieldPatterns.get(entry.getKey()));
75+
}
76+
}
77+
}
78+
return message;
79+
}
80+
81+
private static List<String> getAllSensitiveFieldNames() {
82+
try (final InputStream inputStream = ObfuscateLoggingConverter.class.getResourceAsStream("/obfuscate")) {
83+
if (inputStream == null) {
84+
return Collections.emptyList();
85+
}
86+
return new BufferedReader(new InputStreamReader(inputStream)).lines()
87+
.map(String::trim)
88+
.toList();
89+
} catch (final IOException ex) {
90+
return Collections.emptyList();
91+
}
92+
}
93+
94+
}

src/main/java/br/com/multidatasources/service/v1/BillionaireService.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import br.com.multidatasources.service.v1.idempotency.IdempotencyGenerator;
66
import jakarta.persistence.EntityExistsException;
77
import jakarta.persistence.EntityNotFoundException;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
810
import org.springframework.stereotype.Service;
911
import org.springframework.transaction.annotation.Transactional;
1012

@@ -14,6 +16,8 @@
1416
@Transactional
1517
public class BillionaireService {
1618

19+
private static final Logger log = LoggerFactory.getLogger(BillionaireService.class);
20+
1721
private final BillionaireRepository billionaireRepository;
1822
private final IdempotencyGenerator idempotencyGenerator;
1923

@@ -27,6 +31,7 @@ public BillionaireService(
2731

2832
@Transactional(readOnly = true)
2933
public Billionaire findById(final Long id) {
34+
log.info("Find billionaire by id: {}", id);
3035
return billionaireRepository.findById(id)
3136
.orElseThrow(() -> new EntityNotFoundException(String.format("Register with id %s not found", id)));
3237
}

src/main/resources/application.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ logging:
8080
br.com.multidatasources: INFO
8181
appender: CONSOLE
8282
pattern:
83-
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %X{X-Request-ID} %highlight(%-5level) %magenta([%t]) %msg%n"
83+
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %X{X-Request-ID} %highlight(%-5level) %magenta([%t]) %obfuscate(%msg)%n"
8484

8585
# DATABASE SCHEMA PROPERTIES
8686
schema:

src/main/resources/logback-spring.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<configuration>
3+
<conversionRule conversionWord="obfuscate" converterClass="br.com.multidatasources.config.logging.ObfuscateLoggingConverter" />
34

45
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
56

@@ -22,11 +23,13 @@
2223
<version>[ignore]</version>
2324
<levelValue>[ignore]</levelValue>
2425
<timestamp>[ignore]</timestamp>
26+
<message>[ignore]</message>
2527
</fieldNames>
2628
<provider class="net.logstash.logback.composite.loggingevent.LoggingEventPatternJsonProvider">
2729
<pattern>
2830
{
29-
"timestamp_app": "%d{yyyy-MM-dd HH:mm:ss.SSS}"
31+
"timestamp_app": "%d{yyyy-MM-dd HH:mm:ss.SSS}",
32+
"message": "%obfuscate(%message)"
3033
}
3134
</pattern>
3235
</provider>

src/main/resources/obfuscate

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
billionaire_id
2+
id

src/test/java/br/com/multidatasources/service/v1/BillionaireServiceIntegrationTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import org.junit.jupiter.api.Test;
1212
import org.junit.jupiter.api.extension.ExtendWith;
1313
import org.springframework.beans.factory.annotation.Autowired;
14-
import org.springframework.boot.test.mock.mockito.SpyBean;
14+
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
1515

1616
import java.util.List;
1717

@@ -23,11 +23,11 @@
2323
@ExtendWith(DefaultBillionaireParameterResolverExtension.class)
2424
class BillionaireServiceIntegrationTest {
2525

26-
@SpyBean
26+
@MockitoSpyBean
2727
private IdempotencyGenerator idempotencyGenerator;
2828

2929
@Autowired
30-
@SpyBean
30+
@MockitoSpyBean
3131
private BillionaireRepository billionaireRepository;
3232

3333
@Autowired

0 commit comments

Comments
 (0)