/* * Copyright 2012-2017 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.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; /** * Tests for {@link ConfigurationPropertiesReportEndpoint}. * * @author Dave Syer */ public class ConfigurationPropertiesReportEndpointTests extends AbstractEndpointTests<ConfigurationPropertiesReportEndpoint> { public ConfigurationPropertiesReportEndpointTests() { super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops", true, "endpoints.configprops"); } @Test public void testInvoke() throws Exception { assertThat(getEndpointBean().invoke().size()).isGreaterThan(0); } @Test @SuppressWarnings("unchecked") public void testNaming() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) properties .get("testProperties"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("prefix")).isEqualTo("test"); assertThat(nestedProperties.get("properties")).isNotNull(); } @Test @SuppressWarnings("unchecked") public void entriesWithNullValuesAreNotIncluded() { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) properties .get("testProperties"); assertThat((Map<String, Object>) nestedProperties.get("properties")) .doesNotContainKey("nullValue"); } @Test @SuppressWarnings("unchecked") public void testDefaultKeySanitization() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("******"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("654321"); } @Test @SuppressWarnings("unchecked") public void testKeySanitization() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); report.setKeysToSanitize("property"); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("123456"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******"); } @Test @SuppressWarnings("unchecked") public void testKeySanitizationWithList() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); report.setKeysToSanitize("property"); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("123456"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******"); } @SuppressWarnings("unchecked") @Test public void testKeySanitizationWithCustomPattern() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); report.setKeysToSanitize(".*pass.*"); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("******"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("654321"); } @SuppressWarnings("unchecked") @Test public void testKeySanitizationWithCustomKeysByEnvironment() throws Exception { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, "endpoints.configprops.keys-to-sanitize:property"); 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"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("123456"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******"); } @SuppressWarnings("unchecked") @Test public void testKeySanitizationWithCustomPatternByEnvironment() throws Exception { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, "endpoints.configprops.keys-to-sanitize: .*pass.*"); 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"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("******"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("654321"); } @Test @SuppressWarnings("unchecked") public void testKeySanitizationWithCustomPatternAndKeyByEnvironment() throws Exception { this.context = new AnnotationConfigApplicationContext(); EnvironmentTestUtils.addEnvironment(this.context, "endpoints.configprops.keys-to-sanitize: .*pass.*, property"); 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"); assertThat(nestedProperties).isNotNull(); assertThat(nestedProperties.get("dbPassword")).isEqualTo("******"); assertThat(nestedProperties.get("myTestProperty")).isEqualTo("******"); } @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"); assertThat(nestedProperties).isNotNull(); Map<String, Object> secrets = (Map<String, Object>) nestedProperties .get("secrets"); Map<String, Object> hidden = (Map<String, Object>) nestedProperties.get("hidden"); assertThat(secrets.get("mine")).isEqualTo("******"); assertThat(secrets.get("yours")).isEqualTo("******"); assertThat(hidden.get("mine")).isEqualTo("******"); } @Test @SuppressWarnings("unchecked") public void mixedBoolean() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties.get("mixedBoolean")).isEqualTo(true); } @Test @SuppressWarnings("unchecked") public void listsAreSanitized() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties.get("listItems")).isInstanceOf(List.class); List<Object> list = (List<Object>) nestedProperties.get("listItems"); assertThat(list).hasSize(1); Map<String, Object> item = (Map<String, Object>) list.get(0); assertThat(item.get("somePassword")).isEqualTo("******"); } @Test @SuppressWarnings("unchecked") public void listsOfListsAreSanitized() throws Exception { ConfigurationPropertiesReportEndpoint report = getEndpointBean(); Map<String, Object> properties = report.invoke(); Map<String, Object> nestedProperties = (Map<String, Object>) ((Map<String, Object>) properties .get("testProperties")).get("properties"); assertThat(nestedProperties.get("listOfListItems")).isInstanceOf(List.class); List<List<Object>> listOfLists = (List<List<Object>>) nestedProperties .get("listOfListItems"); assertThat(listOfLists).hasSize(1); List<Object> list = listOfLists.get(0); assertThat(list).hasSize(1); Map<String, Object> item = (Map<String, Object>) list.get(0); assertThat(item.get("somePassword")).isEqualTo("******"); } @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(prefix = "test") public static class TestProperties { private String dbPassword = "123456"; private String myTestProperty = "654321"; private Boolean mixedBoolean = true; private Map<String, Object> secrets = new HashMap<>(); private Hidden hidden = new Hidden(); private List<ListItem> listItems = new ArrayList<>(); private List<List<ListItem>> listOfListItems = new ArrayList<>(); private String nullValue = null; public TestProperties() { this.secrets.put("mine", "myPrivateThing"); this.secrets.put("yours", "yourPrivateThing"); this.listItems.add(new ListItem()); this.listOfListItems.add(Arrays.asList(new ListItem())); } 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; } public boolean isMixedBoolean() { return (this.mixedBoolean == null ? false : this.mixedBoolean); } public void setMixedBoolean(Boolean mixedBoolean) { 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 List<ListItem> getListItems() { return this.listItems; } public void setListItems(List<ListItem> listItems) { this.listItems = listItems; } public List<List<ListItem>> getListOfListItems() { return this.listOfListItems; } public void setListOfListItems(List<List<ListItem>> listOfListItems) { this.listOfListItems = listOfListItems; } public String getNullValue() { return this.nullValue; } public void setNullValue(String nullValue) { this.nullValue = nullValue; } public static class Hidden { private String mine = "mySecret"; public String getMine() { return this.mine; } public void setMine(String mine) { this.mine = mine; } } public static class ListItem { private String somePassword = "secret"; public String getSomePassword() { return this.somePassword; } public void setSomePassword(String somePassword) { this.somePassword = somePassword; } } } }