diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Sanitizer.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Sanitizer.java index 550280d017..a0a0d34530 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Sanitizer.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Sanitizer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,8 @@ package org.springframework.boot.actuate.endpoint; import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -41,16 +43,22 @@ public class Sanitizer { private static final String[] REGEX_PARTS = { "*", "$", "^", "+" }; - private static final String[] DEFAULT_KEYS_TO_SANITIZE = { "password", "secret", "key", "token", ".*credentials.*", "vcap_services", "sun.java.command", "uri", "uris", "address", "addresses" }; + private static final Set DEFAULT_KEYS_TO_SANITIZE = new LinkedHashSet<>(Arrays.asList("password", "secret", + "key", "token", ".*credentials.*", "vcap_services", "sun.java.command")); - private static final String[] URI_USERINFO_KEYS = { "uri", "uris", "address", "addresses" }; + private static final Set URI_USERINFO_KEYS = new LinkedHashSet<>( + Arrays.asList("uri", "uris", "address", "addresses")); private static final Pattern URI_USERINFO_PATTERN = Pattern.compile("[A-Za-z]+://.+:(.*)@.+$"); private Pattern[] keysToSanitize; + static { + DEFAULT_KEYS_TO_SANITIZE.addAll(URI_USERINFO_KEYS); + } + public Sanitizer() { - this(DEFAULT_KEYS_TO_SANITIZE); + this(DEFAULT_KEYS_TO_SANITIZE.toArray(new String[0])); } public Sanitizer(String... keysToSanitize) { @@ -116,19 +124,17 @@ public class Sanitizer { return false; } - private Object sanitizeUris(String uriString) { - // Treat each uri value as possibly containing multiple uris (comma separated) - return Arrays.stream(uriString.split(",")) - .map(this::sanitizeUri) - .collect(Collectors.joining(",")); + private Object sanitizeUris(String value) { + return Arrays.stream(value.split(",")).map(this::sanitizeUri).collect(Collectors.joining(",")); } - private String sanitizeUri(String uriString) { - Matcher matcher = URI_USERINFO_PATTERN.matcher(uriString); + private String sanitizeUri(String value) { + Matcher matcher = URI_USERINFO_PATTERN.matcher(value); String password = matcher.matches() ? matcher.group(1) : null; if (password != null) { - return StringUtils.replace(uriString, ":" + password + "@", ":******@"); + return StringUtils.replace(value, ":" + password + "@", ":******@"); } - return uriString; + return value; } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java index 1620f03a5b..a1b6135bac 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package org.springframework.boot.actuate.context.properties; import java.net.URI; import java.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SanitizerTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SanitizerTests.java index ff9b369d7a..9785411463 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SanitizerTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/SanitizerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,12 +16,12 @@ package org.springframework.boot.actuate.endpoint; +import java.util.stream.Stream; + import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import java.util.stream.Stream; - import static org.assertj.core.api.Assertions.assertThat; /** @@ -49,14 +49,15 @@ class SanitizerTests { @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithSingleEntryWithPasswordShouldBeSanitized(String key) { + void uriWithSingleValueWithPasswordShouldBeSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); - assertThat(sanitizer.sanitize(key, "http://user:password@localhost:8080")).isEqualTo("http://user:******@localhost:8080"); + assertThat(sanitizer.sanitize(key, "http://user:password@localhost:8080")) + .isEqualTo("http://user:******@localhost:8080"); } @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithSingleEntryWithNoPasswordShouldNotBeSanitized(String key) { + void uriWithSingleValueWithNoPasswordShouldNotBeSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); assertThat(sanitizer.sanitize(key, "http://localhost:8080")).isEqualTo("http://localhost:8080"); assertThat(sanitizer.sanitize(key, "http://user@localhost:8080")).isEqualTo("http://user@localhost:8080"); @@ -64,22 +65,24 @@ class SanitizerTests { @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithSingleEntryWithPasswordMatchingOtherPartsOfStringShouldBeSanitized(String key) { + void uriWithSingleValueWithPasswordMatchingOtherPartsOfStringShouldBeSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); - assertThat(sanitizer.sanitize(key, "http://user://@localhost:8080")).isEqualTo("http://user:******@localhost:8080"); + assertThat(sanitizer.sanitize(key, "http://user://@localhost:8080")) + .isEqualTo("http://user:******@localhost:8080"); } @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithMultipleEntriesEachWithPasswordShouldHaveAllSanitized(String key) { + void uriWithMultipleValuesEachWithPasswordShouldHaveAllSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); - assertThat(sanitizer.sanitize(key, "http://user1:password1@localhost:8080,http://user2:password2@localhost:8082")) - .isEqualTo("http://user1:******@localhost:8080,http://user2:******@localhost:8082"); + assertThat( + sanitizer.sanitize(key, "http://user1:password1@localhost:8080,http://user2:password2@localhost:8082")) + .isEqualTo("http://user1:******@localhost:8080,http://user2:******@localhost:8082"); } @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithMultipleEntriesNoneWithPasswordShouldHaveNoneSanitized(String key) { + void uriWithMultipleValuesNoneWithPasswordShouldHaveNoneSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); assertThat(sanitizer.sanitize(key, "http://user@localhost:8080,http://localhost:8082")) .isEqualTo("http://user@localhost:8080,http://localhost:8082"); @@ -87,22 +90,24 @@ class SanitizerTests { @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithMultipleEntriesSomeWithPasswordShouldHaveThoseSanitized(String key) { + void uriWithMultipleValuesSomeWithPasswordShouldHaveThoseSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); - assertThat(sanitizer.sanitize(key, "http://user1:password1@localhost:8080,http://user2@localhost:8082,http://localhost:8083")) - .isEqualTo("http://user1:******@localhost:8080,http://user2@localhost:8082,http://localhost:8083"); + assertThat(sanitizer.sanitize(key, + "http://user1:password1@localhost:8080,http://user2@localhost:8082,http://localhost:8083")).isEqualTo( + "http://user1:******@localhost:8080,http://user2@localhost:8082,http://localhost:8083"); } @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") - void uriWithMultipleEntriesWithPasswordMatchingOtherPartsOfStringShouldBeSanitized(String key) { + void uriWithMultipleValuesWithPasswordMatchingOtherPartsOfStringShouldBeSanitized(String key) { Sanitizer sanitizer = new Sanitizer(); assertThat(sanitizer.sanitize(key, "http://user1://@localhost:8080,http://user2://@localhost:8082")) .isEqualTo("http://user1:******@localhost:8080,http://user2:******@localhost:8082"); } - static private Stream matchingUriUserInfoKeys() { - return Stream.of("uri", "my.uri", "myuri", "uris", "my.uris", "myuris", "address", "my.address", "myaddress", "addresses", "my.addresses", "myaddresses"); + private static Stream matchingUriUserInfoKeys() { + return Stream.of("uri", "my.uri", "myuri", "uris", "my.uris", "myuris", "address", "my.address", "myaddress", + "addresses", "my.addresses", "myaddresses"); } @Test @@ -111,4 +116,5 @@ class SanitizerTests { assertThat(sanitizer.sanitize("verylOCkish", "secret")).isEqualTo("******"); assertThat(sanitizer.sanitize("veryokish", "secret")).isEqualTo("secret"); } + } diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java index fe4fd3beb7..76481d5d12 100644 --- a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/env/EnvironmentEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -257,9 +257,13 @@ class EnvironmentEndpointTests { @Test void addressesPropertyWithMultipleEntriesEachWithSensitiveInfo() { ConfigurableEnvironment environment = new StandardEnvironment(); - TestPropertyValues.of("sensitive.addresses=http://user:password@localhost:8080,http://user2:password2@localhost:8082").applyTo(environment); - EnvironmentEntryDescriptor descriptor = new EnvironmentEndpoint(environment).environmentEntry("sensitive.addresses"); - assertThat(descriptor.getProperty().getValue()).isEqualTo("http://user:******@localhost:8080,http://user2:******@localhost:8082"); + TestPropertyValues + .of("sensitive.addresses=http://user:password@localhost:8080,http://user2:password2@localhost:8082") + .applyTo(environment); + EnvironmentEntryDescriptor descriptor = new EnvironmentEndpoint(environment) + .environmentEntry("sensitive.addresses"); + assertThat(descriptor.getProperty().getValue()) + .isEqualTo("http://user:******@localhost:8080,http://user2:******@localhost:8082"); } private static ConfigurableEnvironment emptyEnvironment() {