diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java index 9c9b938514..4225492220 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfiguration.java @@ -49,6 +49,10 @@ public class ConfigurationPropertiesReportEndpointAutoConfiguration { if (keysToSanitize != null) { endpoint.setKeysToSanitize(keysToSanitize); } + String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize(); + if (additionalKeysToSanitize != null) { + endpoint.keysToSanitize(additionalKeysToSanitize); + } return endpoint; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointProperties.java index 7170f64ab2..d4a2b13835 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -34,6 +34,12 @@ public class ConfigurationPropertiesReportEndpointProperties { */ private String[] keysToSanitize; + /** + * Keys that should be sanitized in addition to those already configured. Keys can be + * simple strings that the property ends with or regular expressions. + */ + private String[] additionalKeysToSanitize; + public String[] getKeysToSanitize() { return this.keysToSanitize; } @@ -42,4 +48,12 @@ public class ConfigurationPropertiesReportEndpointProperties { this.keysToSanitize = keysToSanitize; } + public String[] getAdditionalKeysToSanitize() { + return this.additionalKeysToSanitize; + } + + public void setAdditionalKeysToSanitize(String[] additionalKeysToSanitize) { + this.additionalKeysToSanitize = additionalKeysToSanitize; + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java index c8af552dea..30547155eb 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -47,6 +47,10 @@ public class EnvironmentEndpointAutoConfiguration { if (keysToSanitize != null) { endpoint.setKeysToSanitize(keysToSanitize); } + String[] additionalKeysToSanitize = properties.getAdditionalKeysToSanitize(); + if (additionalKeysToSanitize != null) { + endpoint.keysToSanitize(additionalKeysToSanitize); + } return endpoint; } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointProperties.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointProperties.java index fe753edcff..cd1bfddf13 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointProperties.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -34,6 +34,12 @@ public class EnvironmentEndpointProperties { */ private String[] keysToSanitize; + /** + * Keys that should be sanitized in addition to those already configured. Keys can be + * simple strings that the property ends with or regular expressions. + */ + private String[] additionalKeysToSanitize; + public String[] getKeysToSanitize() { return this.keysToSanitize; } @@ -42,4 +48,12 @@ public class EnvironmentEndpointProperties { this.keysToSanitize = keysToSanitize; } + public String[] getAdditionalKeysToSanitize() { + return this.additionalKeysToSanitize; + } + + public void setAdditionalKeysToSanitize(String[] additionalKeysToSanitize) { + this.additionalKeysToSanitize = additionalKeysToSanitize; + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfigurationTests.java index f9bc7bf608..731a6292a9 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/context/properties/ConfigurationPropertiesReportEndpointAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -64,6 +64,14 @@ class ConfigurationPropertiesReportEndpointAutoConfigurationTests { .run(validateTestProperties("******", "******")); } + @Test + void additionalKeysToSanitizeCanBeConfiguredViaTheEnvironment() { + this.contextRunner.withUserConfiguration(Config.class) + .withPropertyValues("management.endpoint.configprops.additional-keys-to-sanitize: property") + .withPropertyValues("management.endpoints.web.exposure.include=configprops") + .run(validateTestProperties("******", "******")); + } + @Test void runWhenNotExposedShouldNotHaveEndpointBean() { this.contextRunner diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfigurationTests.java index 6965b59bb8..0115bbccd6 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/env/EnvironmentEndpointAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2021 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. @@ -67,6 +67,14 @@ class EnvironmentEndpointAutoConfigurationTests { .run(validateSystemProperties("******", "123456")); } + @Test + void additionalKeysToSanitizeCanBeConfiguredViaTheEnvironment() { + this.contextRunner.withPropertyValues("management.endpoints.web.exposure.include=env") + .withSystemProperties("dbPassword=123456", "apiKey=123456") + .withPropertyValues("management.endpoint.env.additional-keys-to-sanitize=key") + .run(validateSystemProperties("******", "******")); + } + private ContextConsumer validateSystemProperties(String dbPassword, String apiKey) { return (context) -> { assertThat(context).hasSingleBean(EnvironmentEndpoint.class); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java index b7be20f55e..7058a8172b 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java @@ -115,6 +115,10 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext this.sanitizer.setKeysToSanitize(keysToSanitize); } + public void keysToSanitize(String... keysToSanitize) { + this.sanitizer.keysToSanitize(keysToSanitize); + } + @ReadOperation public ApplicationConfigurationProperties configurationProperties() { return extract(this.context, (bean) -> true); 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 1963e783e9..7ba48caa0c 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 @@ -67,8 +67,8 @@ public class Sanitizer { } /** - * Keys that should be sanitized. Keys can be simple strings that the property ends - * with or regular expressions. + * Set the keys that should be sanitized, overwriting any existing configuration. Keys + * can be simple strings that the property ends with or regular expressions. * @param keysToSanitize the keys to sanitize */ public void setKeysToSanitize(String... keysToSanitize) { @@ -79,6 +79,21 @@ public class Sanitizer { } } + /** + * Adds keys that should be sanitized. Keys can be simple strings that the property + * ends with or regular expressions. + * @param keysToSanitize the keys to sanitize + * @since 2.5.0 + */ + public void keysToSanitize(String... keysToSanitize) { + Assert.notNull(keysToSanitize, "KeysToSanitize must not be null"); + int existingKeys = this.keysToSanitize.length; + this.keysToSanitize = Arrays.copyOf(this.keysToSanitize, this.keysToSanitize.length + keysToSanitize.length); + for (int i = 0; i < keysToSanitize.length; i++) { + this.keysToSanitize[i + existingKeys] = getPattern(keysToSanitize[i]); + } + } + private Pattern getPattern(String value) { if (isRegex(value)) { return Pattern.compile(value, Pattern.CASE_INSENSITIVE); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java index d7f0a494f1..bd9118e751 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2021 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. @@ -76,6 +76,10 @@ public class EnvironmentEndpoint { this.sanitizer.setKeysToSanitize(keysToSanitize); } + public void keysToSanitize(String... keysToSanitize) { + this.sanitizer.keysToSanitize(keysToSanitize); + } + @ReadOperation public EnvironmentDescriptor environment(@Nullable String pattern) { if (StringUtils.hasText(pattern)) { 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 472f71f181..3742e22755 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 @@ -48,6 +48,23 @@ class SanitizerTests { assertThat(sanitizer.sanitize("sun.java.command", "--spring.redis.password=pa55w0rd")).isEqualTo("******"); } + @Test + void whenAdditionalKeysAreAddedValuesOfBothThemAndTheDefaultKeysAreSanitized() { + Sanitizer sanitizer = new Sanitizer(); + sanitizer.keysToSanitize("find", "confidential"); + assertThat(sanitizer.sanitize("password", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("my-password", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("my-OTHER.paSSword", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("somesecret", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("somekey", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("token", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("sometoken", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("find", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("sun.java.command", "--spring.redis.password=pa55w0rd")).isEqualTo("******"); + assertThat(sanitizer.sanitize("confidential", "secret")).isEqualTo("******"); + assertThat(sanitizer.sanitize("private", "secret")).isEqualTo("secret"); + } + @ParameterizedTest(name = "key = {0}") @MethodSource("matchingUriUserInfoKeys") void uriWithSingleValueWithPasswordShouldBeSanitized(String key) { diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc index af57fcf490..2888e6b9ed 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto.adoc @@ -2333,14 +2333,10 @@ See also the section on "`<://