Consider prefixes when sanitizing `/configprops`
Update ConfigurationPropertiesReportEndpoint so that property prefixes are also considered when sanitizing values. Fixes gh-4415
This commit is contained in:
parent
4aefe9f856
commit
bd20b5419e
|
|
@ -111,7 +111,7 @@ public class ConfigurationPropertiesReportEndpoint
|
|||
Map<String, Object> root = new HashMap<String, Object>();
|
||||
String prefix = extractPrefix(context, beanFactoryMetaData, beanName, bean);
|
||||
root.put("prefix", prefix);
|
||||
root.put("properties", sanitize(safeSerialize(mapper, bean, prefix)));
|
||||
root.put("properties", sanitize(prefix, safeSerialize(mapper, bean, prefix)));
|
||||
result.put(beanName, root);
|
||||
}
|
||||
if (context.getParent() != null) {
|
||||
|
|
@ -231,15 +231,18 @@ public class ConfigurationPropertiesReportEndpoint
|
|||
* @return the sanitized map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> sanitize(Map<String, Object> map) {
|
||||
private Map<String, Object> sanitize(String prefix, Map<String, Object> map) {
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String qualifiedKey = (prefix.length() == 0 ? prefix : prefix + ".") + key;
|
||||
Object value = entry.getValue();
|
||||
if (value instanceof Map) {
|
||||
map.put(key, sanitize((Map<String, Object>) value));
|
||||
map.put(key, sanitize(qualifiedKey, (Map<String, Object>) value));
|
||||
}
|
||||
else {
|
||||
map.put(key, this.sanitizer.sanitize(key, value));
|
||||
value = this.sanitizer.sanitize(key, value);
|
||||
value = this.sanitizer.sanitize(qualifiedKey, value);
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.boot.actuate.endpoint;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
|
@ -135,8 +136,8 @@ public class ConfigurationPropertiesReportEndpointTests
|
|||
assertEquals("654321", nestedProperties.get("myTestProperty"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testKeySanitizationWithCustomPatternAndKeyByEnvironment()
|
||||
throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
|
|
@ -153,6 +154,29 @@ public class ConfigurationPropertiesReportEndpointTests
|
|||
assertEquals("******", nestedProperties.get("myTestProperty"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testKeySanitizationWithCustomPatternUsingCompositeKeys()
|
||||
throws Exception {
|
||||
// gh-4415
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
EnvironmentTestUtils.addEnvironment(this.context,
|
||||
"endpoints.configprops.keys-to-sanitize: .*\\.secrets\\..*, .*\\.hidden\\..*");
|
||||
this.context.register(Config.class);
|
||||
this.context.refresh();
|
||||
ConfigurationPropertiesReportEndpoint report = getEndpointBean();
|
||||
Map<String, Object> properties = report.invoke();
|
||||
Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties
|
||||
.get("testProperties")).get("properties");
|
||||
assertNotNull(nestedProperties);
|
||||
Map<String, Object> secrets = (Map<String, Object>) nestedProperties
|
||||
.get("secrets");
|
||||
Map<String, Object> hidden = (Map<String, Object>) nestedProperties.get("hidden");
|
||||
assertEquals("******", secrets.get("mine"));
|
||||
assertEquals("******", secrets.get("yours"));
|
||||
assertEquals("******", hidden.get("mine"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void mixedBoolean() throws Exception {
|
||||
|
|
@ -197,6 +221,15 @@ public class ConfigurationPropertiesReportEndpointTests
|
|||
|
||||
private Boolean mixedBoolean = true;
|
||||
|
||||
private Map<String, Object> secrets = new HashMap<String, Object>();
|
||||
|
||||
private Hidden hidden = new Hidden();
|
||||
|
||||
public TestProperties() {
|
||||
this.secrets.put("mine", "myPrivateThing");
|
||||
this.secrets.put("yours", "yourPrivateThing");
|
||||
}
|
||||
|
||||
public String getDbPassword() {
|
||||
return this.dbPassword;
|
||||
}
|
||||
|
|
@ -221,5 +254,35 @@ public class ConfigurationPropertiesReportEndpointTests
|
|||
this.mixedBoolean = mixedBoolean;
|
||||
}
|
||||
|
||||
public Map<String, Object> getSecrets() {
|
||||
return this.secrets;
|
||||
}
|
||||
|
||||
public void setSecrets(Map<String, Object> secrets) {
|
||||
this.secrets = secrets;
|
||||
}
|
||||
|
||||
public Hidden getHidden() {
|
||||
return this.hidden;
|
||||
}
|
||||
|
||||
public void setHidden(Hidden hidden) {
|
||||
this.hidden = hidden;
|
||||
}
|
||||
|
||||
public static class Hidden {
|
||||
|
||||
private String mine = "mySecret";
|
||||
|
||||
public String getMine() {
|
||||
return this.mine;
|
||||
}
|
||||
|
||||
public void setMine(String mine) {
|
||||
this.mine = mine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue