diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java
index fca2a4eea4..95fa306e7c 100644
--- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java
+++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java
@@ -34,8 +34,9 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* annotated classes.
*
*
- * To protect sensitive information from being exposed, configure property names by using
- * endpoints.configprops.keys_to_sanitize.
+ * To protect sensitive information from being exposed, certain property values are masked
+ * if their names end with a set of configurable values (default "password" and "secret").
+ * Configure property names by using {@link #setKeysToSanitize(String[])}.
*
* @author Christian Dupuis
*/
@@ -66,12 +67,17 @@ public class ConfigurationPropertiesReportEndpoint extends
this.keysToSanitize = keysToSanitize;
}
- @Override
- @SuppressWarnings("unchecked")
@RequestMapping
@ResponseBody
public Map invoke() {
- Map beans = this.context
+ Map beans = extract(this.context);
+ return beans;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map extract(ApplicationContext context) {
+
+ Map beans = context
.getBeansWithAnnotation(ConfigurationProperties.class);
// Serialize beans into map structure and sanitize values
@@ -81,6 +87,10 @@ public class ConfigurationPropertiesReportEndpoint extends
beans.put(entry.getKey(), sanitize(value));
}
+ if (context.getParent() != null) {
+ beans.put("parent", extract(context.getParent()));
+ }
+
return beans;
}
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointParentTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointParentTests.java
new file mode 100644
index 0000000000..e45923e967
--- /dev/null
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointParentTests.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2013 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.boot.actuate.endpoint;
+
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Test;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class ConfigurationPropertiesReportEndpointParentTests {
+
+ private AnnotationConfigApplicationContext context;
+
+ @After
+ public void close() {
+ if (this.context != null) {
+ this.context.close();
+ if (this.context.getParent() != null) {
+ ((ConfigurableApplicationContext) this.context.getParent()).close();
+ }
+ }
+ }
+
+ @Test
+ public void testInvoke() throws Exception {
+ AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
+ parent.register(Parent.class);
+ parent.refresh();
+ this.context = new AnnotationConfigApplicationContext();
+ this.context.setParent(parent);
+ this.context.register(Config.class);
+ this.context.refresh();
+ ConfigurationPropertiesReportEndpoint endpoint = this.context
+ .getBean(ConfigurationPropertiesReportEndpoint.class);
+ Map result = endpoint.invoke();
+ assertTrue(result.containsKey("parent"));
+ assertEquals(3, result.size()); // the endpoint, the test props and the parent
+ // System.err.println(result);
+ }
+
+ @Configuration
+ @EnableConfigurationProperties
+ public static class Parent {
+ @Bean
+ public TestProperties testProperties() {
+ return new TestProperties();
+ }
+ }
+
+ @Configuration
+ @EnableConfigurationProperties
+ public static class Config {
+
+ @Bean
+ public ConfigurationPropertiesReportEndpoint endpoint() {
+ return new ConfigurationPropertiesReportEndpoint();
+ }
+
+ @Bean
+ public TestProperties testProperties() {
+ return new TestProperties();
+ }
+
+ }
+
+ @ConfigurationProperties(name = "test")
+ public static class TestProperties {
+
+ private String myTestProperty = "654321";
+
+ public String getMyTestProperty() {
+ return this.myTestProperty;
+ }
+
+ public void setMyTestProperty(String myTestProperty) {
+ this.myTestProperty = myTestProperty;
+ }
+
+ }
+}
diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointTests.java
index 0e7edecb8a..3fad25b028 100644
--- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointTests.java
+++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointTests.java
@@ -68,6 +68,15 @@ public class ConfigurationPropertiesReportEndpointTests extends
assertEquals("******", nestedProperties.get("myTestProperty"));
}
+ @Configuration
+ @EnableConfigurationProperties
+ public static class Parent {
+ @Bean
+ public TestProperties testProperties() {
+ return new TestProperties();
+ }
+ }
+
@Configuration
@EnableConfigurationProperties
public static class Config {
@@ -82,29 +91,30 @@ public class ConfigurationPropertiesReportEndpointTests extends
return new TestProperties();
}
- @ConfigurationProperties(name = "test")
- public static class TestProperties {
+ }
- private String dbPassword = "123456";
+ @ConfigurationProperties(name = "test")
+ public static class TestProperties {
- private String myTestProperty = "654321";
+ private String dbPassword = "123456";
- public String getDbPassword() {
- return this.dbPassword;
- }
-
- public void setDbPassword(String dbPassword) {
- this.dbPassword = dbPassword;
- }
-
- public String getMyTestProperty() {
- return this.myTestProperty;
- }
-
- public void setMyTestProperty(String myTestProperty) {
- this.myTestProperty = myTestProperty;
- }
+ private String myTestProperty = "654321";
+ public String getDbPassword() {
+ return this.dbPassword;
}
+
+ public void setDbPassword(String dbPassword) {
+ this.dbPassword = dbPassword;
+ }
+
+ public String getMyTestProperty() {
+ return this.myTestProperty;
+ }
+
+ public void setMyTestProperty(String myTestProperty) {
+ this.myTestProperty = myTestProperty;
+ }
+
}
}