Skip to content

Commit f27bb39

Browse files
committed
Sanitize configuration properties that are nested beneath a List
Closes gh-8197
1 parent 05dbc15 commit f27bb39

File tree

2 files changed

+77
-2
lines changed

2 files changed

+77
-2
lines changed

spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpoint.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -239,6 +239,9 @@ private Map<String, Object> sanitize(String prefix, Map<String, Object> map) {
239239
if (value instanceof Map) {
240240
map.put(key, sanitize(qualifiedKey, (Map<String, Object>) value));
241241
}
242+
else if (value instanceof List) {
243+
map.put(key, sanitize(qualifiedKey, (List<Object>) value));
244+
}
242245
else {
243246
value = this.sanitizer.sanitize(key, value);
244247
value = this.sanitizer.sanitize(qualifiedKey, value);
@@ -248,6 +251,24 @@ private Map<String, Object> sanitize(String prefix, Map<String, Object> map) {
248251
return map;
249252
}
250253

254+
@SuppressWarnings("unchecked")
255+
private List<Object> sanitize(String prefix, List<Object> list) {
256+
List<Object> sanitized = new ArrayList<Object>();
257+
for (Object item : list) {
258+
if (item instanceof Map) {
259+
sanitized.add(sanitize(prefix, (Map<String, Object>) item));
260+
}
261+
else if (item instanceof List) {
262+
sanitize(prefix, (List<Object>) item);
263+
}
264+
else {
265+
item = this.sanitizer.sanitize(prefix, item);
266+
sanitized.add(this.sanitizer.sanitize(prefix, item));
267+
}
268+
}
269+
return sanitized;
270+
}
271+
251272
/**
252273
* Extension to {@link JacksonAnnotationIntrospector} to suppress CGLIB generated bean
253274
* properties.

spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ConfigurationPropertiesReportEndpointTests.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2016 the original author or authors.
2+
* Copyright 2012-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,7 +16,9 @@
1616

1717
package org.springframework.boot.actuate.endpoint;
1818

19+
import java.util.ArrayList;
1920
import java.util.HashMap;
21+
import java.util.List;
2022
import java.util.Map;
2123

2224
import org.junit.Test;
@@ -85,6 +87,19 @@ public void testKeySanitization() throws Exception {
8587
assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******");
8688
}
8789

90+
@Test
91+
@SuppressWarnings("unchecked")
92+
public void testKeySanitizationWithList() throws Exception {
93+
ConfigurationPropertiesReportEndpoint report = getEndpointBean();
94+
report.setKeysToSanitize("property");
95+
Map<String, Object> properties = report.invoke();
96+
Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties
97+
.get("testProperties")).get("properties");
98+
assertThat(nestedProperties).isNotNull();
99+
assertThat(nestedProperties.get("dbPassword")).isEqualTo("123456");
100+
assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******");
101+
}
102+
88103
@SuppressWarnings("unchecked")
89104
@Test
90105
public void testKeySanitizationWithCustomPattern() throws Exception {
@@ -183,6 +198,20 @@ public void mixedBoolean() throws Exception {
183198
assertThat(nestedProperties.get("mixedBoolean")).isEqualTo(true);
184199
}
185200

201+
@Test
202+
@SuppressWarnings("unchecked")
203+
public void listsAreSanitized() throws Exception {
204+
ConfigurationPropertiesReportEndpoint report = getEndpointBean();
205+
Map<String, Object> properties = report.invoke();
206+
Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties
207+
.get("testProperties")).get("properties");
208+
assertThat(nestedProperties.get("listItems")).isInstanceOf(List.class);
209+
List<Object> list = (List<Object>) nestedProperties.get("listItems");
210+
assertThat(list).hasSize(1);
211+
Map<String, Object> item = (Map<String, Object>) list.get(0);
212+
assertThat(item.get("somePassword")).isEqualTo("******");
213+
}
214+
186215
@Configuration
187216
@EnableConfigurationProperties
188217
public static class Parent {
@@ -223,9 +252,12 @@ public static class TestProperties {
223252

224253
private Hidden hidden = new Hidden();
225254

255+
private List<ListItem> listItems = new ArrayList<ListItem>();
256+
226257
public TestProperties() {
227258
this.secrets.put("mine", "myPrivateThing");
228259
this.secrets.put("yours", "yourPrivateThing");
260+
this.listItems.add(new ListItem());
229261
}
230262

231263
public String getDbPassword() {
@@ -268,6 +300,14 @@ public void setHidden(Hidden hidden) {
268300
this.hidden = hidden;
269301
}
270302

303+
public List<ListItem> getListItems() {
304+
return this.listItems;
305+
}
306+
307+
public void setListItems(List<ListItem> listItems) {
308+
this.listItems = listItems;
309+
}
310+
271311
public static class Hidden {
272312

273313
private String mine = "mySecret";
@@ -282,6 +322,20 @@ public void setMine(String mine) {
282322

283323
}
284324

325+
public static class ListItem {
326+
327+
private String somePassword = "secret";
328+
329+
public String getSomePassword() {
330+
return this.somePassword;
331+
}
332+
333+
public void setSomePassword(String somePassword) {
334+
this.somePassword = somePassword;
335+
}
336+
337+
}
338+
285339
}
286340

287341
}

0 commit comments

Comments
 (0)