Skip to content

Commit b4d8c2f

Browse files
authored
Copied Sanitizer from Spring Boot 2.7.18. Removed @ConditionalOnMissingBean from Sanitizer bean definition (#129)
1 parent d27181c commit b4d8c2f

File tree

74 files changed

+517
-74
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+517
-74
lines changed

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/config/QuickFixJClientEndpointAutoConfiguration.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,7 +74,6 @@ public SessionScheduleFactory sessionSchedule() {
7474
}
7575

7676
@Bean
77-
@ConditionalOnMissingBean
7877
public Sanitizer clientActuatorSanitizer() {
7978
return new Sanitizer();
8079
}

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/config/QuickFixJServerEndpointAutoConfiguration.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,7 +74,6 @@ public SessionScheduleFactory sessionSchedule() {
7474
}
7575

7676
@Bean
77-
@ConditionalOnMissingBean
7877
public Sanitizer serverActuatorSanitizer() {
7978
return new Sanitizer();
8079
}

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/endpoint/AbstractQuickFixJEndpoint.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/endpoint/QuickFixJClientEndpoint.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/endpoint/QuickFixJServerEndpoint.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

quickfixj-spring-boot-actuator/src/main/java/io/allune/quickfixj/spring/boot/actuate/health/QuickFixJSessionHealthIndicator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright 2017-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.boot.actuate.endpoint;
17+
18+
import java.util.ArrayList;
19+
import java.util.Arrays;
20+
import java.util.Collections;
21+
import java.util.LinkedHashSet;
22+
import java.util.List;
23+
import java.util.Set;
24+
import java.util.regex.Matcher;
25+
import java.util.regex.Pattern;
26+
import java.util.stream.Collectors;
27+
28+
import org.springframework.util.Assert;
29+
import org.springframework.util.StringUtils;
30+
31+
/**
32+
* Strategy that should be used by endpoint implementations to sanitize potentially
33+
* sensitive keys.
34+
*
35+
* @author Christian Dupuis
36+
* @author Toshiaki Maki
37+
* @author Phillip Webb
38+
* @author Nicolas Lejeune
39+
* @author Stephane Nicoll
40+
* @author HaiTao Zhang
41+
* @author Chris Bono
42+
* @author David Good
43+
* @author Madhura Bhave
44+
* @since 2.0.0
45+
*/
46+
47+
/**
48+
* Borrowed from https://github.com/spring-projects/spring-boot/blob/2.7.x/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Sanitizer.java
49+
* as Sanitizer in Spring Boot 3 is not backward compatible with the version shipped in Spring Boot 2
50+
*/
51+
public class Sanitizer {
52+
53+
private static final String[] REGEX_PARTS = { "*", "$", "^", "+" };
54+
55+
private static final Set<String> DEFAULT_KEYS_TO_SANITIZE = new LinkedHashSet<>(
56+
Arrays.asList("password", "secret", "key", "token", ".*credentials.*", "vcap_services",
57+
"^vcap\\.services.*$", "sun.java.command", "^spring[._]application[._]json$"));
58+
59+
private static final Set<String> URI_USERINFO_KEYS = new LinkedHashSet<>(
60+
Arrays.asList("uri", "uris", "url", "urls", "address", "addresses"));
61+
62+
private static final Pattern URI_USERINFO_PATTERN = Pattern
63+
.compile("^\\[?[A-Za-z][A-Za-z0-9\\+\\.\\-]+://.+:(.*)@.+$");
64+
65+
private Pattern[] keysToSanitize;
66+
67+
private final List<SanitizingFunction> sanitizingFunctions = new ArrayList<>();
68+
69+
static {
70+
DEFAULT_KEYS_TO_SANITIZE.addAll(URI_USERINFO_KEYS);
71+
}
72+
73+
/**
74+
* Create a new {@link Sanitizer} instance with a default set of keys to sanitize.
75+
*/
76+
public Sanitizer() {
77+
this(DEFAULT_KEYS_TO_SANITIZE.toArray(new String[0]));
78+
}
79+
80+
/**
81+
* Create a new {@link Sanitizer} instance with specific keys to sanitize.
82+
* @param keysToSanitize the keys to sanitize
83+
*/
84+
public Sanitizer(String... keysToSanitize) {
85+
this(Collections.emptyList(), keysToSanitize);
86+
}
87+
88+
/**
89+
* Create a new {@link Sanitizer} instance with a default set of keys to sanitize and
90+
* additional sanitizing functions.
91+
* @param sanitizingFunctions the sanitizing functions to apply
92+
* @since 2.6.0
93+
*/
94+
public Sanitizer(Iterable<SanitizingFunction> sanitizingFunctions) {
95+
this(sanitizingFunctions, DEFAULT_KEYS_TO_SANITIZE.toArray(new String[0]));
96+
}
97+
98+
/**
99+
* Create a new {@link Sanitizer} instance with specific keys to sanitize and
100+
* additional sanitizing functions.
101+
* @param sanitizingFunctions the sanitizing functions to apply
102+
* @param keysToSanitize the keys to sanitize
103+
* @since 2.6.0
104+
*/
105+
public Sanitizer(Iterable<SanitizingFunction> sanitizingFunctions, String... keysToSanitize) {
106+
sanitizingFunctions.forEach(this.sanitizingFunctions::add);
107+
this.sanitizingFunctions.add(getDefaultSanitizingFunction());
108+
setKeysToSanitize(keysToSanitize);
109+
}
110+
111+
private SanitizingFunction getDefaultSanitizingFunction() {
112+
return (data) -> {
113+
Object sanitizedValue = sanitize(data.getKey(), data.getValue());
114+
return data.withValue(sanitizedValue);
115+
};
116+
}
117+
118+
/**
119+
* Set the keys that should be sanitized, overwriting any existing configuration. Keys
120+
* can be simple strings that the property ends with or regular expressions.
121+
* @param keysToSanitize the keys to sanitize
122+
*/
123+
public void setKeysToSanitize(String... keysToSanitize) {
124+
Assert.notNull(keysToSanitize, "KeysToSanitize must not be null");
125+
this.keysToSanitize = new Pattern[keysToSanitize.length];
126+
for (int i = 0; i < keysToSanitize.length; i++) {
127+
this.keysToSanitize[i] = getPattern(keysToSanitize[i]);
128+
}
129+
}
130+
131+
/**
132+
* Adds keys that should be sanitized. Keys can be simple strings that the property
133+
* ends with or regular expressions.
134+
* @param keysToSanitize the keys to sanitize
135+
* @since 2.5.0
136+
*/
137+
public void keysToSanitize(String... keysToSanitize) {
138+
Assert.notNull(keysToSanitize, "KeysToSanitize must not be null");
139+
int existingKeys = this.keysToSanitize.length;
140+
this.keysToSanitize = Arrays.copyOf(this.keysToSanitize, this.keysToSanitize.length + keysToSanitize.length);
141+
for (int i = 0; i < keysToSanitize.length; i++) {
142+
this.keysToSanitize[i + existingKeys] = getPattern(keysToSanitize[i]);
143+
}
144+
}
145+
146+
private Pattern getPattern(String value) {
147+
if (isRegex(value)) {
148+
return Pattern.compile(value, Pattern.CASE_INSENSITIVE);
149+
}
150+
return Pattern.compile(".*" + value + "$", Pattern.CASE_INSENSITIVE);
151+
}
152+
153+
private boolean isRegex(String value) {
154+
for (String part : REGEX_PARTS) {
155+
if (value.contains(part)) {
156+
return true;
157+
}
158+
}
159+
return false;
160+
}
161+
162+
/**
163+
* Sanitize the given value if necessary.
164+
* @param key the key to sanitize
165+
* @param value the value
166+
* @return the potentially sanitized value
167+
*/
168+
public Object sanitize(String key, Object value) {
169+
if (value == null) {
170+
return null;
171+
}
172+
for (Pattern pattern : this.keysToSanitize) {
173+
if (pattern.matcher(key).matches()) {
174+
if (keyIsUriWithUserInfo(pattern)) {
175+
return sanitizeUris(value.toString());
176+
}
177+
return SanitizableData.SANITIZED_VALUE;
178+
}
179+
}
180+
return value;
181+
}
182+
183+
/**
184+
* Sanitize the value from the given {@link SanitizableData} using the available
185+
* {@link SanitizingFunction}s.
186+
* @param data the sanitizable data
187+
* @return the potentially updated data
188+
* @since 2.6.0
189+
*/
190+
public Object sanitize(SanitizableData data) {
191+
Object value = data.getValue();
192+
if (value == null) {
193+
return null;
194+
}
195+
for (SanitizingFunction sanitizingFunction : this.sanitizingFunctions) {
196+
data = sanitizingFunction.apply(data);
197+
Object sanitizedValue = data.getValue();
198+
if (!value.equals(sanitizedValue)) {
199+
return sanitizedValue;
200+
}
201+
}
202+
return value;
203+
}
204+
205+
private boolean keyIsUriWithUserInfo(Pattern pattern) {
206+
for (String uriKey : URI_USERINFO_KEYS) {
207+
if (pattern.matcher(uriKey).matches()) {
208+
return true;
209+
}
210+
}
211+
return false;
212+
}
213+
214+
private Object sanitizeUris(String value) {
215+
return Arrays.stream(value.split(",")).map(this::sanitizeUri).collect(Collectors.joining(","));
216+
}
217+
218+
private String sanitizeUri(String value) {
219+
Matcher matcher = URI_USERINFO_PATTERN.matcher(value);
220+
String password = matcher.matches() ? matcher.group(1) : null;
221+
if (password != null) {
222+
return StringUtils.replace(value, ":" + password + "@", ":" + SanitizableData.SANITIZED_VALUE + "@");
223+
}
224+
return value;
225+
}
226+
227+
}

quickfixj-spring-boot-actuator/src/test/java/io/allune/quickfixj/spring/boot/actuate/config/AbstractQuickFixJBaseEndpointAutoConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

quickfixj-spring-boot-actuator/src/test/java/io/allune/quickfixj/spring/boot/actuate/config/QuickFixJClientEndpointAutoConfigurationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

quickfixj-spring-boot-actuator/src/test/java/io/allune/quickfixj/spring/boot/actuate/config/QuickFixJClientEndpointWebIntegrationTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2017-2023 the original author or authors.
2+
* Copyright 2017-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)