Sanitize password in URI properties

See gh-17939
This commit is contained in:
HaiTao Zhang 2019-08-22 11:18:34 -07:00 committed by Madhura Bhave
parent 0fee0ca71c
commit d49a2ec98e
4 changed files with 72 additions and 1 deletions

View File

@ -16,9 +16,11 @@
package org.springframework.boot.actuate.endpoint;
import java.net.URI;
import java.util.regex.Pattern;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Strategy that should be used by endpoint implementations to sanitize potentially
@ -29,6 +31,7 @@ import org.springframework.util.Assert;
* @author Phillip Webb
* @author Nicolas Lejeune
* @author Stephane Nicoll
* @author HaiTao Zhang
* @since 2.0.0
*/
public class Sanitizer {
@ -38,7 +41,7 @@ public class Sanitizer {
private Pattern[] keysToSanitize;
public Sanitizer() {
this("password", "secret", "key", "token", ".*credentials.*", "vcap_services", "sun.java.command");
this("password", "secret", "key", "token", ".*credentials.*", "vcap_services", "sun.java.command", "uri");
}
public Sanitizer(String... keysToSanitize) {
@ -86,10 +89,29 @@ public class Sanitizer {
}
for (Pattern pattern : this.keysToSanitize) {
if (pattern.matcher(key).matches()) {
if (pattern.matcher("uri").matches()) {
return sanitizeUri(value);
}
return "******";
}
}
return value;
}
private Object sanitizeUri(Object value) {
URI uri = URI.create(value.toString());
String userInfo = uri.getUserInfo();
if (!StringUtils.hasText(userInfo) || userInfo.split(":").length == 0) {
return value;
}
String[] parts = userInfo.split(":");
String userName = parts[0];
if (StringUtils.hasText(userName)) {
String sanitizedPassword = "******";
return uri.getScheme() + "://" + userName + ":" + sanitizedPassword + "@" + uri.getHost() + ":"
+ uri.getPort() + uri.getPath();
}
return value;
}
}

View File

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.context.properties;
import java.net.URI;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
@ -46,6 +47,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Dave Syer
* @author Andy Wilkinson
* @author Stephane Nicoll
* @author HaiTao Zhang
*/
class ConfigurationPropertiesReportEndpointTests {
@ -174,6 +176,22 @@ class ConfigurationPropertiesReportEndpointTests {
});
}
@Test
void sanitizedUriWithSensitiveInfo() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans().get("testProperties").getProperties();
assertThat(nestedProperties.get("sensitiveUri")).isEqualTo("http://user:******@localhost:8080");
});
}
@Test
void sanitizedUriWithNoPassword() {
load((context, properties) -> {
Map<String, Object> nestedProperties = properties.getBeans().get("testProperties").getProperties();
assertThat(nestedProperties.get("noPasswordUri")).isEqualTo("http://user:******@localhost:8080");
});
}
@Test
@SuppressWarnings("unchecked")
void listsOfListsAreSanitized() {
@ -266,6 +284,10 @@ class ConfigurationPropertiesReportEndpointTests {
private Duration duration = Duration.ofSeconds(10);
private URI sensitiveUri = URI.create("http://user:password@localhost:8080");
private URI noPasswordUri = URI.create("http://user:p@localhost:8080");
TestProperties() {
this.secrets.put("mine", "myPrivateThing");
this.secrets.put("yours", "yourPrivateThing");
@ -377,6 +399,22 @@ class ConfigurationPropertiesReportEndpointTests {
this.duration = duration;
}
public void setSensitiveUri(URI sensitiveUri) {
this.sensitiveUri = sensitiveUri;
}
public URI getSensitiveUri() {
return this.sensitiveUri;
}
public void setNoPasswordUri(URI noPasswordUri) {
this.noPasswordUri = noPasswordUri;
}
public URI getNoPasswordUri() {
return this.noPasswordUri;
}
public static class Hidden {
private String mine = "mySecret";

View File

@ -40,6 +40,8 @@ class SanitizerTests {
assertThat(sanitizer.sanitize("sometoken", "secret")).isEqualTo("******");
assertThat(sanitizer.sanitize("find", "secret")).isEqualTo("secret");
assertThat(sanitizer.sanitize("sun.java.command", "--spring.redis.password=pa55w0rd")).isEqualTo("******");
assertThat(sanitizer.sanitize("my.uri", "http://user:password@localhost:8080"))
.isEqualTo("http://user:******@localhost:8080");
}
@Test

View File

@ -49,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Stephane Nicoll
* @author Madhura Bhave
* @author Andy Wilkinson
* @author HaiTao Zhang
*/
class EnvironmentEndpointTests {
@ -244,6 +245,14 @@ class EnvironmentEndpointTests {
assertThat(sources.get("two").getProperties().get("a").getValue()).isEqualTo("apple");
}
@Test
void uriPropertryWithSensitiveInfo() {
ConfigurableEnvironment environment = new StandardEnvironment();
TestPropertyValues.of("sensitive.uri=http://user:password@localhost:8080").applyTo(environment);
EnvironmentEntryDescriptor descriptor = new EnvironmentEndpoint(environment).environmentEntry("sensitive.uri");
assertThat(descriptor.getProperty().getValue()).isEqualTo("http://user:******@localhost:8080");
}
private static ConfigurableEnvironment emptyEnvironment() {
StandardEnvironment environment = new StandardEnvironment();
environment.getPropertySources().remove(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME);