Merge branch '1.2.x'
This commit is contained in:
@@ -17,10 +17,6 @@
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
@@ -38,6 +34,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties.Security;
|
||||
import org.springframework.boot.actuate.condition.ConditionalOnEnabledEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
|
||||
@@ -53,17 +50,14 @@ import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||
import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext;
|
||||
@@ -73,14 +67,10 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
@@ -347,78 +337,4 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Conditional} that checks whether or not an endpoint is enabled. Matches if
|
||||
* the value of the {@code endpoints.<name>.enabled} property is {@code true}. Does
|
||||
* not match if the property's value or {@code enabledByDefault} is {@code false}.
|
||||
* Otherwise, matches if the value of the {@code endpoints.enabled} property is
|
||||
* {@code true} or if the property is not configured.
|
||||
*
|
||||
* @since 1.2.4
|
||||
*/
|
||||
@Conditional(OnEnabledEndpointCondition.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public static @interface ConditionalOnEnabledEndpoint {
|
||||
|
||||
/**
|
||||
* The name of the endpoint.
|
||||
* @return The name of the endpoint
|
||||
*/
|
||||
public String value();
|
||||
|
||||
/**
|
||||
* Returns whether or not the endpoint is enabled by default.
|
||||
* @return {@code true} if the endpoint is enabled by default, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean enabledByDefault() default true;
|
||||
|
||||
}
|
||||
|
||||
private static class OnEnabledEndpointCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
AnnotationAttributes annotationAttributes = AnnotationAttributes
|
||||
.fromMap(metadata
|
||||
.getAnnotationAttributes(ConditionalOnEnabledEndpoint.class
|
||||
.getName()));
|
||||
String endpointName = annotationAttributes.getString("value");
|
||||
boolean enabledByDefault = annotationAttributes
|
||||
.getBoolean("enabledByDefault");
|
||||
ConditionOutcome specificEndpointOutcome = determineSpecificEndpointOutcome(
|
||||
endpointName, enabledByDefault, context);
|
||||
if (specificEndpointOutcome != null) {
|
||||
return specificEndpointOutcome;
|
||||
}
|
||||
return determineAllEndpointsOutcome(context);
|
||||
|
||||
}
|
||||
|
||||
private ConditionOutcome determineSpecificEndpointOutcome(String endpointName,
|
||||
boolean enabledByDefault, ConditionContext context) {
|
||||
RelaxedPropertyResolver endpointPropertyResolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints." + endpointName + ".");
|
||||
if (endpointPropertyResolver.containsProperty("enabled") || !enabledByDefault) {
|
||||
boolean match = endpointPropertyResolver.getProperty("enabled",
|
||||
Boolean.class, enabledByDefault);
|
||||
return new ConditionOutcome(match, "The " + endpointName + " is "
|
||||
+ (match ? "enabled" : "disabled"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConditionOutcome determineAllEndpointsOutcome(ConditionContext context) {
|
||||
RelaxedPropertyResolver allEndpointsPropertyResolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints.");
|
||||
boolean match = Boolean.valueOf(allEndpointsPropertyResolver.getProperty(
|
||||
"enabled", "true"));
|
||||
return new ConditionOutcome(match, "All endpoints are "
|
||||
+ (match ? "enabled" : "disabled") + " by default");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -135,14 +135,12 @@ public class MetricFilterAutoConfiguration {
|
||||
}
|
||||
|
||||
private boolean is4xxClientError(int status) {
|
||||
HttpStatus httpStatus = HttpStatus.OK;
|
||||
try {
|
||||
httpStatus = HttpStatus.valueOf(status);
|
||||
return HttpStatus.valueOf(status).is4xxClientError();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// not convertible
|
||||
return false;
|
||||
}
|
||||
return httpStatus.is4xxClientError();
|
||||
}
|
||||
|
||||
private String getKey(String string) {
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.condition;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
* {@link Conditional} that checks whether or not an endpoint is enabled. Matches if the
|
||||
* value of the {@code endpoints.<name>.enabled} property is {@code true}. Does not match
|
||||
* if the property's value or {@code enabledByDefault} is {@code false}. Otherwise,
|
||||
* matches if the value of the {@code endpoints.enabled} property is {@code true} or if
|
||||
* the property is not configured.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.2.4
|
||||
*/
|
||||
@Conditional(OnEnabledEndpointCondition.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface ConditionalOnEnabledEndpoint {
|
||||
|
||||
/**
|
||||
* The name of the endpoint.
|
||||
* @return The name of the endpoint
|
||||
*/
|
||||
public String value();
|
||||
|
||||
/**
|
||||
* Returns whether or not the endpoint is enabled by default.
|
||||
* @return {@code true} if the endpoint is enabled by default, otherwise {@code false}
|
||||
*/
|
||||
public boolean enabledByDefault() default true;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.condition;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
|
||||
/**
|
||||
* {@link Condition} that checks whether or not an endpoint is enabled.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class OnEnabledEndpointCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
AnnotationAttributes annotationAttributes = AnnotationAttributes.fromMap(metadata
|
||||
.getAnnotationAttributes(ConditionalOnEnabledEndpoint.class.getName()));
|
||||
String endpointName = annotationAttributes.getString("value");
|
||||
boolean enabledByDefault = annotationAttributes.getBoolean("enabledByDefault");
|
||||
ConditionOutcome outcome = determineEndpointOutcome(endpointName,
|
||||
enabledByDefault, context);
|
||||
if (outcome != null) {
|
||||
return outcome;
|
||||
}
|
||||
return determineAllEndpointsOutcome(context);
|
||||
}
|
||||
|
||||
private ConditionOutcome determineEndpointOutcome(String endpointName,
|
||||
boolean enabledByDefault, ConditionContext context) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints." + endpointName + ".");
|
||||
if (resolver.containsProperty("enabled") || !enabledByDefault) {
|
||||
boolean match = resolver.getProperty("enabled", Boolean.class,
|
||||
enabledByDefault);
|
||||
return new ConditionOutcome(match, "The " + endpointName + " is "
|
||||
+ (match ? "enabled" : "disabled"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConditionOutcome determineAllEndpointsOutcome(ConditionContext context) {
|
||||
RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints.");
|
||||
boolean match = Boolean.valueOf(resolver.getProperty("enabled", "true"));
|
||||
return new ConditionOutcome(match, "All endpoints are "
|
||||
+ (match ? "enabled" : "disabled") + " by default");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2012-2015 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* {@code @Condition} annotations and supporting classes.
|
||||
*/
|
||||
package org.springframework.boot.actuate.condition;
|
||||
@@ -324,9 +324,7 @@ public class ConfigurationPropertiesReportEndpoint extends
|
||||
private boolean isReadable(BeanDescription beanDesc, BeanPropertyWriter writer) {
|
||||
String parentType = beanDesc.getType().getRawClass().getName();
|
||||
String type = writer.getPropertyType().getName();
|
||||
AnnotatedMethod setter = beanDesc.findMethod(
|
||||
"set" + StringUtils.capitalize(writer.getName()),
|
||||
new Class<?>[] { writer.getPropertyType() });
|
||||
AnnotatedMethod setter = findSetter(beanDesc, writer);
|
||||
// If there's a setter, we assume it's OK to report on the value,
|
||||
// similarly, if there's no setter but the package names match, we assume
|
||||
// that its a nested class used solely for binding to config props, so it
|
||||
@@ -336,6 +334,19 @@ public class ConfigurationPropertiesReportEndpoint extends
|
||||
|| ClassUtils.getPackageName(parentType).equals(
|
||||
ClassUtils.getPackageName(type));
|
||||
}
|
||||
|
||||
private AnnotatedMethod findSetter(BeanDescription beanDesc,
|
||||
BeanPropertyWriter writer) {
|
||||
String name = "set" + StringUtils.capitalize(writer.getName());
|
||||
Class<?> type = writer.getPropertyType();
|
||||
AnnotatedMethod setter = beanDesc.findMethod(name, new Class<?>[] { type });
|
||||
// The enabled property of endpoints returns a boolean primitive but is set
|
||||
// using a Boolean class
|
||||
if (setter == null && type.equals(Boolean.TYPE)) {
|
||||
setter = beanDesc.findMethod(name, new Class<?>[] { Boolean.class });
|
||||
}
|
||||
return setter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,11 +44,11 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
@@ -209,44 +209,36 @@ public class ManagementSecurityAutoConfigurationTests {
|
||||
PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders
|
||||
.webAppContextSetup((WebApplicationContext) this.context)
|
||||
.addFilters(
|
||||
this.context.getBean("springSecurityFilterChain", Filter.class))
|
||||
.build();
|
||||
|
||||
Filter filter = this.context.getBean("springSecurityFilterChain", Filter.class);
|
||||
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.addFilters(filter).build();
|
||||
|
||||
// no user (Main)
|
||||
mockMvc.perform(
|
||||
MockMvcRequestBuilders.get("/"))
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/"))
|
||||
.andExpect(MockMvcResultMatchers.status().isUnauthorized())
|
||||
.andExpect(
|
||||
MockMvcResultMatchers.header().string("www-authenticate",
|
||||
Matchers.containsString("realm=\"Spring\"")));
|
||||
.andExpect(springAuthenticateRealmHeader());
|
||||
|
||||
// invalid user (Main)
|
||||
mockMvc.perform(
|
||||
MockMvcRequestBuilders.get("/").header("authorization", "Basic xxx"))
|
||||
.andExpect(MockMvcResultMatchers.status().isUnauthorized())
|
||||
.andExpect(
|
||||
MockMvcResultMatchers.header().string("www-authenticate",
|
||||
Matchers.containsString("realm=\"Spring\"")));
|
||||
.andExpect(springAuthenticateRealmHeader());
|
||||
|
||||
// no user (Management)
|
||||
mockMvc.perform(
|
||||
MockMvcRequestBuilders.get("/beans"))
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/beans"))
|
||||
.andExpect(MockMvcResultMatchers.status().isUnauthorized())
|
||||
.andExpect(
|
||||
MockMvcResultMatchers.header().string("www-authenticate",
|
||||
Matchers.containsString("realm=\"Spring\"")));
|
||||
.andExpect(springAuthenticateRealmHeader());
|
||||
|
||||
// invalid user (Management)
|
||||
mockMvc.perform(
|
||||
MockMvcRequestBuilders.get("/beans").header("authorization", "Basic xxx"))
|
||||
.andExpect(MockMvcResultMatchers.status().isUnauthorized())
|
||||
.andExpect(
|
||||
MockMvcResultMatchers.header().string("www-authenticate",
|
||||
Matchers.containsString("realm=\"Spring\"")));
|
||||
.andExpect(springAuthenticateRealmHeader());
|
||||
}
|
||||
|
||||
private ResultMatcher springAuthenticateRealmHeader() {
|
||||
return MockMvcResultMatchers.header().string("www-authenticate",
|
||||
Matchers.containsString("realm=\"Spring\""));
|
||||
}
|
||||
|
||||
@EnableGlobalAuthentication
|
||||
@@ -254,9 +246,8 @@ public class ManagementSecurityAutoConfigurationTests {
|
||||
static class AuthenticationConfig {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
auth.inMemoryAuthentication().withUser("user").password("password")
|
||||
.roles("USER");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -151,6 +152,17 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
assertEquals("******", nestedProperties.get("myTestProperty"));
|
||||
}
|
||||
|
||||
@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");
|
||||
System.out.println(nestedProperties);
|
||||
assertThat(nestedProperties.get("mixedBoolean"), equalTo((Object) true));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties
|
||||
public static class Parent {
|
||||
@@ -183,6 +195,8 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
|
||||
private String myTestProperty = "654321";
|
||||
|
||||
private Boolean mixedBoolean = true;
|
||||
|
||||
public String getDbPassword() {
|
||||
return this.dbPassword;
|
||||
}
|
||||
@@ -199,5 +213,13 @@ public class ConfigurationPropertiesReportEndpointTests extends
|
||||
this.myTestProperty = myTestProperty;
|
||||
}
|
||||
|
||||
public boolean isMixedBoolean() {
|
||||
return (this.mixedBoolean == null ? false : this.mixedBoolean);
|
||||
}
|
||||
|
||||
public void setMixedBoolean(Boolean mixedBoolean) {
|
||||
this.mixedBoolean = mixedBoolean;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user