From bb55f49396fd32190dd3ea403c2ef4698c0b0ba9 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 1 Aug 2017 10:05:09 +0100 Subject: [PATCH] Remove concept of sensitivity from Actuator's endpoints Closes gh-9924 --- ...anagementWebSecurityAutoConfiguration.java | 65 +----- .../CloudFoundryDiscoveryMvcEndpoint.java | 2 +- .../actuate/endpoint/AbstractEndpoint.java | 34 +--- .../boot/actuate/endpoint/Endpoint.java | 7 - .../actuate/endpoint/EndpointProperties.java | 38 +--- .../boot/actuate/endpoint/HealthEndpoint.java | 2 +- .../boot/actuate/endpoint/InfoEndpoint.java | 2 +- .../actuate/endpoint/ShutdownEndpoint.java | 2 +- .../actuate/endpoint/jmx/EndpointMBean.java | 5 - .../mvc/AbstractEndpointMvcAdapter.java | 5 - .../endpoint/mvc/AbstractMvcEndpoint.java | 26 +-- .../mvc/AbstractNamedMvcEndpoint.java | 11 +- .../endpoint/mvc/AuditEventsMvcEndpoint.java | 2 +- .../endpoint/mvc/EndpointHandlerMapping.java | 2 +- .../endpoint/mvc/HeapdumpMvcEndpoint.java | 2 +- .../endpoint/mvc/JolokiaMvcEndpoint.java | 2 +- .../endpoint/mvc/LogFileMvcEndpoint.java | 2 +- .../actuate/endpoint/mvc/MvcEndpoint.java | 6 - .../mvc/MvcEndpointSecurityInterceptor.java | 4 - ...ointMBeanExportAutoConfigurationTests.java | 4 +- .../EndpointWebMvcAutoConfigurationTests.java | 5 - .../autoconfigure/LinksEnhancerTests.java | 6 +- ...mentWebSecurityAutoConfigurationTests.java | 24 --- .../CloudFoundryHealthMvcEndpointTests.java | 1 - .../endpoint/AbstractEndpointTests.java | 55 +---- .../AutoConfigurationReportEndpointTests.java | 2 +- .../actuate/endpoint/BeansEndpointTests.java | 2 +- ...gurationPropertiesReportEndpointTests.java | 2 +- .../actuate/endpoint/DumpEndpointTests.java | 4 +- .../endpoint/EnvironmentEndpointTests.java | 2 +- .../actuate/endpoint/FlywayEndpointTests.java | 2 +- .../actuate/endpoint/HealthEndpointTests.java | 2 +- .../actuate/endpoint/InfoEndpointTests.java | 2 +- .../endpoint/LiquibaseEndpointTests.java | 3 +- .../endpoint/LoggersEndpointTests.java | 2 +- .../endpoint/MetricsEndpointTests.java | 2 +- .../endpoint/ShutdownEndpointTests.java | 3 +- .../actuate/endpoint/TraceEndpointTests.java | 2 +- .../jmx/EndpointMBeanExporterTests.java | 4 +- .../endpoint/mvc/InfoMvcEndpointTests.java | 3 +- ...vcEndpointWithNoInfoContributorsTests.java | 2 + .../mvc/MvcEndpointIntegrationTests.java | 30 +-- .../MvcEndpointSecurityInterceptorTests.java | 20 +- ...rityHealthMvcEndpointIntegrationTests.java | 25 --- ...tyMvcEndpointSecurityInterceptorTests.java | 3 +- .../appendix-application-properties.adoc | 20 -- .../asciidoc/production-ready-features.adoc | 191 ++++++------------ .../CorsSampleActuatorApplicationTests.java | 13 +- ...gementAddressActuatorApplicationTests.java | 16 +- ...entPathSampleActuatorApplicationTests.java | 13 +- ...AndPathSampleActuatorApplicationTests.java | 7 +- ...entPortSampleActuatorApplicationTests.java | 9 +- .../actuator/NonSensitiveHealthTests.java | 55 ----- .../SampleActuatorApplicationTests.java | 11 +- ...letPathSampleActuatorApplicationTests.java | 13 +- 55 files changed, 173 insertions(+), 606 deletions(-) delete mode 100644 spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/NonSensitiveHealthTests.java diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfiguration.java index 1b61c92112b..c29c749d76a 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfiguration.java @@ -26,7 +26,6 @@ import javax.annotation.PostConstruct; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.ObjectProvider; -import org.springframework.boot.actuate.endpoint.Endpoint; import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping; import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint; import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint; @@ -62,7 +61,6 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity.I import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; @@ -77,11 +75,7 @@ import org.springframework.util.StringUtils; * {@link EnableAutoConfiguration Auto-configuration} for security of framework endpoints. * Many aspects of the behavior can be controller with {@link ManagementServerProperties} * via externalized application properties (or via an bean definition of that type to set - * the defaults). - *

- * The framework {@link Endpoint}s (used to expose application information to operations) - * include a {@link Endpoint#isSensitive() sensitive} configuration option which will be - * used as a security hint by the filter created here. + * the defaults).. * * @author Dave Syer * @author Andy Wilkinson @@ -126,7 +120,6 @@ public class ManagementWebSecurityAutoConfiguration { .getRequestMatcher(this.contextResolver); configurer.requestMatchers(requestMatcher); } - } } @@ -223,8 +216,6 @@ public class ManagementWebSecurityAutoConfiguration { http.exceptionHandling().authenticationEntryPoint(entryPoint); // Match all the requests for actuator endpoints ... http.requestMatcher(matcher); - // ... but permitAll() for the non-sensitive ones - configurePermittedRequests(http.authorizeRequests()); http.httpBasic().authenticationEntryPoint(entryPoint).and().cors(); // No cookies for management endpoints by default http.csrf().disable(); @@ -258,38 +249,9 @@ public class ManagementWebSecurityAutoConfiguration { return entryPoint; } - private void configurePermittedRequests( - ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry requests) { - requests.requestMatchers(new LazyEndpointPathRequestMatcher( - this.contextResolver, EndpointPaths.SENSITIVE)).authenticated(); - // Permit access to the non-sensitive endpoints - requests.requestMatchers(new LazyEndpointPathRequestMatcher( - this.contextResolver, EndpointPaths.NON_SENSITIVE)).permitAll(); - } - } - private enum EndpointPaths { - - ALL, - - NON_SENSITIVE { - - @Override - protected boolean isIncluded(MvcEndpoint endpoint) { - return !endpoint.isSensitive(); - } - - }, - - SENSITIVE { - - @Override - protected boolean isIncluded(MvcEndpoint endpoint) { - return endpoint.isSensitive(); - } - - }; + private static class EndpointPaths { public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) { if (endpointHandlerMapping == null) { @@ -298,24 +260,18 @@ public class ManagementWebSecurityAutoConfiguration { Set endpoints = endpointHandlerMapping.getEndpoints(); Set paths = new LinkedHashSet<>(endpoints.size()); for (MvcEndpoint endpoint : endpoints) { - if (isIncluded(endpoint)) { - String path = endpointHandlerMapping.getPath(endpoint.getPath()); - paths.add(path); - if (!path.equals("")) { - paths.add(path + "/**"); - // Add Spring MVC-generated additional paths - paths.add(path + ".*"); - } - paths.add(path + "/"); + String path = endpointHandlerMapping.getPath(endpoint.getPath()); + paths.add(path); + if (!path.equals("")) { + paths.add(path + "/**"); + // Add Spring MVC-generated additional paths + paths.add(path + ".*"); } + paths.add(path + "/"); } return paths.toArray(new String[paths.size()]); } - protected boolean isIncluded(MvcEndpoint endpoint) { - return true; - } - } private static class LazyEndpointPathRequestMatcher implements RequestMatcher { @@ -342,7 +298,8 @@ public class ManagementWebSecurityAutoConfiguration { return matcher; } // Match everything, including the sensitive and non-sensitive paths - return new LazyEndpointPathRequestMatcher(contextResolver, EndpointPaths.ALL); + return new LazyEndpointPathRequestMatcher(contextResolver, + new EndpointPaths()); } LazyEndpointPathRequestMatcher(ManagementContextResolver contextResolver, diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryDiscoveryMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryDiscoveryMvcEndpoint.java index a409c652bff..a1ae48e7dd9 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryDiscoveryMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryDiscoveryMvcEndpoint.java @@ -41,7 +41,7 @@ class CloudFoundryDiscoveryMvcEndpoint extends AbstractMvcEndpoint { private final Set endpoints; CloudFoundryDiscoveryMvcEndpoint(Set endpoints) { - super("", false); + super(""); this.endpoints = endpoints; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java index a81c2e99d7b..b3debdedf6b 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/AbstractEndpoint.java @@ -41,47 +41,27 @@ public abstract class AbstractEndpoint implements Endpoint, EnvironmentAwa */ private String id; - private final boolean sensitiveDefault; - - /** - * Mark if the endpoint exposes sensitive information. - */ - private Boolean sensitive; - /** * Enable the endpoint. */ private Boolean enabled; - /** - * Create a new sensitive endpoint instance. The endpoint will enabled flag will be - * based on the spring {@link Environment} unless explicitly set. - * @param id the endpoint ID - */ - public AbstractEndpoint(String id) { - this(id, true); - } - /** * Create a new endpoint instance. The endpoint will enabled flag will be based on the * spring {@link Environment} unless explicitly set. * @param id the endpoint ID - * @param sensitive if the endpoint is sensitive by default */ - public AbstractEndpoint(String id, boolean sensitive) { + public AbstractEndpoint(String id) { setId(id); - this.sensitiveDefault = sensitive; } /** * Create a new endpoint instance. * @param id the endpoint ID - * @param sensitive if the endpoint is sensitive * @param enabled if the endpoint is enabled or not. */ - public AbstractEndpoint(String id, boolean sensitive, boolean enabled) { + public AbstractEndpoint(String id, boolean enabled) { setId(id); - this.sensitiveDefault = sensitive; this.enabled = enabled; } @@ -115,14 +95,4 @@ public abstract class AbstractEndpoint implements Endpoint, EnvironmentAwa this.enabled = enabled; } - @Override - public boolean isSensitive() { - return EndpointProperties.isSensitive(this.environment, this.sensitive, - this.sensitiveDefault); - } - - public void setSensitive(Boolean sensitive) { - this.sensitive = sensitive; - } - } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java index d25791d763d..3c2647ba3fd 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/Endpoint.java @@ -42,13 +42,6 @@ public interface Endpoint { */ boolean isEnabled(); - /** - * Return if the endpoint is sensitive, i.e. may return data that the average user - * should not see. Mappings can use this as a security hint. - * @return if the endpoint is sensitive - */ - boolean isSensitive(); - /** * Called to invoke the endpoint. * @return the results of the invocation diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointProperties.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointProperties.java index ae722967859..1c09a4928d9 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointProperties.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/EndpointProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * 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. @@ -30,18 +30,11 @@ public class EndpointProperties { private static final String ENDPOINTS_ENABLED_PROPERTY = "endpoints.enabled"; - private static final String ENDPOINTS_SENSITIVE_PROPERTY = "endpoints.sensitive"; - /** * Enable endpoints. */ private Boolean enabled = true; - /** - * Default endpoint sensitive setting. - */ - private Boolean sensitive; - public Boolean getEnabled() { return this.enabled; } @@ -50,14 +43,6 @@ public class EndpointProperties { this.enabled = enabled; } - public Boolean getSensitive() { - return this.sensitive; - } - - public void setSensitive(Boolean sensitive) { - this.sensitive = sensitive; - } - /** * Determine if an endpoint is enabled based on its specific property and taking into * account the global default. @@ -76,25 +61,4 @@ public class EndpointProperties { return true; } - /** - * Determine if an endpoint is sensitive based on its specific property and taking - * into account the global default. - * @param environment the Spring environment or {@code null}. - * @param sensitive the endpoint property or {@code null} - * @param sensitiveDefault the default setting to use if no environment property is - * defined - * @return if the endpoint is sensitive - */ - public static boolean isSensitive(Environment environment, Boolean sensitive, - boolean sensitiveDefault) { - if (sensitive != null) { - return sensitive; - } - if (environment != null - && environment.containsProperty(ENDPOINTS_SENSITIVE_PROPERTY)) { - return environment.getProperty(ENDPOINTS_SENSITIVE_PROPERTY, Boolean.class); - } - return sensitiveDefault; - } - } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/HealthEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/HealthEndpoint.java index 5c6b621e4c0..3a62ed7801c 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/HealthEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/HealthEndpoint.java @@ -49,7 +49,7 @@ public class HealthEndpoint extends AbstractEndpoint { */ public HealthEndpoint(HealthAggregator healthAggregator, Map healthIndicators) { - super("health", false); + super("health"); Assert.notNull(healthAggregator, "HealthAggregator must not be null"); Assert.notNull(healthIndicators, "HealthIndicators must not be null"); CompositeHealthIndicator healthIndicator = new CompositeHealthIndicator( diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InfoEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InfoEndpoint.java index 7c38b68d774..40cef3f38b5 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InfoEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InfoEndpoint.java @@ -41,7 +41,7 @@ public class InfoEndpoint extends AbstractEndpoint> { * @param infoContributors the info contributors to use */ public InfoEndpoint(List infoContributors) { - super("info", false); + super("info"); Assert.notNull(infoContributors, "Info contributors must not be null"); this.infoContributors = infoContributors; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java index 5c6f124be44..6c36ecc8439 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ShutdownEndpoint.java @@ -50,7 +50,7 @@ public class ShutdownEndpoint extends AbstractEndpoint> * Create a new {@link ShutdownEndpoint} instance. */ public ShutdownEndpoint() { - super("shutdown", true, false); + super("shutdown", false); } @Override diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java index 1a36478fba5..ce6e3e71d7e 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBean.java @@ -64,11 +64,6 @@ public abstract class EndpointMBean implements JmxEndpoint { return this.endpoint.isEnabled(); } - @ManagedAttribute(description = "Indicates whether the underlying endpoint exposes sensitive information") - public boolean isSensitive() { - return this.endpoint.isSensitive(); - } - @Override public String getIdentity() { return ObjectUtils.getIdentityHexString(getEndpoint()); diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractEndpointMvcAdapter.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractEndpointMvcAdapter.java index 1415a63e282..f3e60d21232 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractEndpointMvcAdapter.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractEndpointMvcAdapter.java @@ -80,11 +80,6 @@ public abstract class AbstractEndpointMvcAdapter> this.path = path; } - @Override - public boolean isSensitive() { - return this.delegate.isSensitive(); - } - @Override @SuppressWarnings("rawtypes") public Class getEndpointType() { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractMvcEndpoint.java index c01dd43e79d..efff32ed5ce 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractMvcEndpoint.java @@ -46,22 +46,8 @@ public abstract class AbstractMvcEndpoint */ private Boolean enabled; - /** - * Mark if the endpoint exposes sensitive information. - */ - private Boolean sensitive; - - private final boolean sensitiveDefault; - - public AbstractMvcEndpoint(String path, boolean sensitive) { + public AbstractMvcEndpoint(String path) { setPath(path); - this.sensitiveDefault = sensitive; - } - - public AbstractMvcEndpoint(String path, boolean sensitive, boolean enabled) { - setPath(path); - this.sensitiveDefault = sensitive; - this.enabled = enabled; } @Override @@ -93,16 +79,6 @@ public abstract class AbstractMvcEndpoint this.enabled = enabled; } - @Override - public boolean isSensitive() { - return EndpointProperties.isSensitive(this.environment, this.sensitive, - this.sensitiveDefault); - } - - public void setSensitive(Boolean sensitive) { - this.sensitive = sensitive; - } - @Override @SuppressWarnings("rawtypes") public Class getEndpointType() { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java index b0a0adcf9a3..353070ad12a 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AbstractNamedMvcEndpoint.java @@ -31,15 +31,8 @@ public abstract class AbstractNamedMvcEndpoint extends AbstractMvcEndpoint private final String name; - public AbstractNamedMvcEndpoint(String name, String path, boolean sensitive) { - super(path, sensitive); - Assert.hasLength(name, "Name must not be empty"); - this.name = name; - } - - public AbstractNamedMvcEndpoint(String name, String path, boolean sensitive, - boolean enabled) { - super(path, sensitive, enabled); + public AbstractNamedMvcEndpoint(String name, String path) { + super(path); Assert.hasLength(name, "Name must not be empty"); this.name = name; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java index b0ec145a7b9..38fce97c76b 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/AuditEventsMvcEndpoint.java @@ -42,7 +42,7 @@ public class AuditEventsMvcEndpoint extends AbstractNamedMvcEndpoint { private final AuditEventRepository auditEventRepository; public AuditEventsMvcEndpoint(AuditEventRepository auditEventRepository) { - super("auditevents", "/auditevents", true); + super("auditevents", "/auditevents"); Assert.notNull(auditEventRepository, "AuditEventRepository must not be null"); this.auditEventRepository = auditEventRepository; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java index 8e6dac888d4..d5c153f4276 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/EndpointHandlerMapping.java @@ -91,7 +91,7 @@ public class EndpointHandlerMapping extends AbstractEndpointHandlerMapping endpoints; private EndpointLinksMvcEndpoint(Set endpoints) { - super("", false); + super(""); this.endpoints = endpoints; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HeapdumpMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HeapdumpMvcEndpoint.java index af9b6c8f278..03a1300d4cc 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HeapdumpMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/HeapdumpMvcEndpoint.java @@ -68,7 +68,7 @@ public class HeapdumpMvcEndpoint extends AbstractNamedMvcEndpoint { } protected HeapdumpMvcEndpoint(long timeout) { - super("heapdump", "/heapdump", true); + super("heapdump", "/heapdump"); this.timeout = timeout; } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java index 89d73561347..58a949559cb 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/JolokiaMvcEndpoint.java @@ -50,7 +50,7 @@ public class JolokiaMvcEndpoint extends AbstractNamedMvcEndpoint implements private final ServletWrappingController controller = new ServletWrappingController(); public JolokiaMvcEndpoint() { - super("jolokia", "/jolokia", true); + super("jolokia", "/jolokia"); this.controller.setServletClass(AgentServlet.class); this.controller.setServletName("jolokia"); } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LogFileMvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LogFileMvcEndpoint.java index 66d16e4733c..4971c86c12a 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LogFileMvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/LogFileMvcEndpoint.java @@ -58,7 +58,7 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint { private File externalFile; public LogFileMvcEndpoint() { - super("logfile", "/logfile", true); + super("logfile", "/logfile"); } public File getExternalFile() { diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpoint.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpoint.java index ab208ed009b..969bfcfc907 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpoint.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpoint.java @@ -48,12 +48,6 @@ public interface MvcEndpoint { */ String getPath(); - /** - * Return if the endpoint exposes sensitive information. - * @return if the endpoint is sensitive - */ - boolean isSensitive(); - /** * Return the type of {@link Endpoint} exposed, or {@code null} if this * {@link MvcEndpoint} exposes information that cannot be represented as a traditional diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptor.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptor.java index a8bc37ae864..7430b36d5d0 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptor.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptor.java @@ -69,10 +69,6 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter { && !(handlerMethod.getBean() instanceof MvcEndpoint)) { return true; } - MvcEndpoint mvcEndpoint = (MvcEndpoint) handlerMethod.getBean(); - if (!mvcEndpoint.isSensitive()) { - return true; - } if (isUserAllowedAccess(request)) { return true; } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java index 5c921482ecc..34d5b5e34bf 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointMBeanExportAutoConfigurationTests.java @@ -178,7 +178,7 @@ public class EndpointMBeanExportAutoConfigurationTests { public static class ManagedEndpoint extends AbstractEndpoint { public ManagedEndpoint() { - super("managed", true); + super("managed"); } @Override @@ -200,7 +200,7 @@ public class EndpointMBeanExportAutoConfigurationTests { class Nested extends AbstractEndpoint { Nested() { - super("managed", true); + super("managed"); } @Override diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java index 72b0f109cb3..84981a97c41 100755 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/EndpointWebMvcAutoConfigurationTests.java @@ -867,11 +867,6 @@ public class EndpointWebMvcAutoConfigurationTests { return "/endpoint"; } - @Override - public boolean isSensitive() { - return true; - } - @Override @SuppressWarnings("rawtypes") public Class getEndpointType() { diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancerTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancerTests.java index a443143b2bf..05b99e58c5a 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancerTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/LinksEnhancerTests.java @@ -64,7 +64,7 @@ public class LinksEnhancerTests { @Test public void usePathAsRelIfNameNotAvailable() throws Exception { - MvcEndpoint endpoint = new NoNameTestMvcEndpoint("/a", false); + MvcEndpoint endpoint = new NoNameTestMvcEndpoint("/a"); LinksEnhancer enhancer = getLinksEnhancer(Collections.singletonList(endpoint)); ResourceSupport support = new ResourceSupport(); enhancer.addEndpointLinks(support, ""); @@ -143,8 +143,8 @@ public class LinksEnhancerTests { private static class NoNameTestMvcEndpoint extends AbstractMvcEndpoint { - NoNameTestMvcEndpoint(String path, boolean sensitive) { - super(path, sensitive); + NoNameTestMvcEndpoint(String path) { + super(path); } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfigurationTests.java index 2336638e99f..877a5198766 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/ManagementWebSecurityAutoConfigurationTests.java @@ -57,9 +57,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; /** * Tests for {@link ManagementWebSecurityAutoConfiguration}. @@ -226,27 +223,6 @@ public class ManagementWebSecurityAutoConfigurationTests { .andExpect(springAuthenticateRealmHeader()); } - @Test - public void testMarkAllEndpointsSensitive() throws Exception { - // gh-4368 - this.context = new AnnotationConfigWebApplicationContext(); - this.context.setServletContext(new MockServletContext()); - this.context.register(WebConfiguration.class); - TestPropertyValues.of("endpoints.sensitive:true").applyTo(this.context); - this.context.refresh(); - - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context) // - .apply(springSecurity()) // - .build(); - - mockMvc // - .perform(get("/health")) // - .andExpect(status().isUnauthorized()); - mockMvc // - .perform(get("/info")) // - .andExpect(status().isUnauthorized()); - } - private ResultMatcher springAuthenticateRealmHeader() { return MockMvcResultMatchers.header().string("www-authenticate", Matchers.containsString("realm=\"Spring\"")); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryHealthMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryHealthMvcEndpointTests.java index a09dbf6cfcb..b8203503e1e 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryHealthMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/cloudfoundry/CloudFoundryHealthMvcEndpointTests.java @@ -41,7 +41,6 @@ public class CloudFoundryHealthMvcEndpointTests { CloudFoundryHealthMvcEndpoint mvc = new CloudFoundryHealthMvcEndpoint(endpoint); given(endpoint.invoke()) .willReturn(new Health.Builder().up().withDetail("foo", "bar").build()); - given(endpoint.isSensitive()).willReturn(false); Object result = mvc.invoke(null, null); assertThat(result instanceof Health).isTrue(); assertThat(((Health) result).getStatus() == Status.UP).isTrue(); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AbstractEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AbstractEndpointTests.java index 7ab7fe9b2d1..00d285e1409 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AbstractEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AbstractEndpointTests.java @@ -49,16 +49,13 @@ public abstract class AbstractEndpointTests> { private final String id; - private final boolean sensitive; - private final String property; public AbstractEndpointTests(Class configClass, Class type, String id, - boolean sensitive, String property) { + String property) { this.configClass = configClass; this.type = type; this.id = id; - this.sensitive = sensitive; this.property = property; } @@ -81,11 +78,6 @@ public abstract class AbstractEndpointTests> { assertThat(getEndpointBean().getId()).isEqualTo(this.id); } - @Test - public void isSensitive() throws Exception { - assertThat(getEndpointBean().isSensitive()).isEqualTo(this.sensitive); - } - @Test public void idOverride() throws Exception { this.context = new AnnotationConfigApplicationContext(); @@ -95,31 +87,6 @@ public abstract class AbstractEndpointTests> { assertThat(getEndpointBean().getId()).isEqualTo("myid"); } - @Test - public void isSensitiveOverride() throws Exception { - this.context = new AnnotationConfigApplicationContext(); - PropertySource propertySource = new MapPropertySource("test", - Collections.singletonMap(this.property + ".sensitive", - String.valueOf(!this.sensitive))); - this.context.getEnvironment().getPropertySources().addFirst(propertySource); - this.context.register(this.configClass); - this.context.refresh(); - assertThat(getEndpointBean().isSensitive()).isEqualTo(!this.sensitive); - } - - @Test - public void isSensitiveOverrideWithGlobal() throws Exception { - this.context = new AnnotationConfigApplicationContext(); - Map properties = new HashMap<>(); - properties.put("endpoint.sensitive", this.sensitive); - properties.put(this.property + ".sensitive", String.valueOf(!this.sensitive)); - PropertySource propertySource = new MapPropertySource("test", properties); - this.context.getEnvironment().getPropertySources().addFirst(propertySource); - this.context.register(this.configClass); - this.context.refresh(); - assertThat(getEndpointBean().isSensitive()).isEqualTo(!this.sensitive); - } - @Test public void isEnabledByDefault() throws Exception { assertThat(getEndpointBean().isEnabled()).isTrue(); @@ -181,26 +148,6 @@ public abstract class AbstractEndpointTests> { } } - @Test - public void isAllEndpointsSensitive() throws Exception { - testGlobalEndpointsSensitive(true); - } - - @Test - public void isAllEndpointsNotSensitive() throws Exception { - testGlobalEndpointsSensitive(false); - } - - private void testGlobalEndpointsSensitive(boolean sensitive) { - this.context = new AnnotationConfigApplicationContext(); - PropertySource propertySource = new MapPropertySource("test", Collections - .singletonMap("endpoints.sensitive", sensitive)); - this.context.getEnvironment().getPropertySources().addFirst(propertySource); - this.context.register(this.configClass); - this.context.refresh(); - assertThat(getEndpointBean().isSensitive()).isEqualTo(sensitive); - } - @SuppressWarnings("unchecked") protected T getEndpointBean() { return (T) this.context.getBean(this.type); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AutoConfigurationReportEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AutoConfigurationReportEndpointTests.java index 471a05880fb..da1f331d2ae 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AutoConfigurationReportEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/AutoConfigurationReportEndpointTests.java @@ -47,7 +47,7 @@ public class AutoConfigurationReportEndpointTests extends AbstractEndpointTests { public AutoConfigurationReportEndpointTests() { - super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig", true, + super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig", "endpoints.autoconfig"); } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/BeansEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/BeansEndpointTests.java index b7fb1ca62d2..57559ea0af1 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/BeansEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/BeansEndpointTests.java @@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class BeansEndpointTests extends AbstractEndpointTests { public BeansEndpointTests() { - super(Config.class, BeansEndpoint.class, "beans", true, "endpoints.beans"); + super(Config.class, BeansEndpoint.class, "beans", "endpoints.beans"); } @Test 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 032ea2b8814..74f482bf31b 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 @@ -43,7 +43,7 @@ public class ConfigurationPropertiesReportEndpointTests public ConfigurationPropertiesReportEndpointTests() { super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops", - true, "endpoints.configprops"); + "endpoints.configprops"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/DumpEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/DumpEndpointTests.java index 40cc2233b32..170560dec73 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/DumpEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/DumpEndpointTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * 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. @@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class DumpEndpointTests extends AbstractEndpointTests { public DumpEndpointTests() { - super(Config.class, DumpEndpoint.class, "dump", true, "endpoints.dump"); + super(Config.class, DumpEndpoint.class, "dump", "endpoints.dump"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpointTests.java index 240a186b2e8..ef7d6a4272e 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/EnvironmentEndpointTests.java @@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class EnvironmentEndpointTests extends AbstractEndpointTests { public EnvironmentEndpointTests() { - super(Config.class, EnvironmentEndpoint.class, "env", true, "endpoints.env"); + super(Config.class, EnvironmentEndpoint.class, "env", "endpoints.env"); } @Override diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/FlywayEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/FlywayEndpointTests.java index ffbfa5e5cd8..d33d6e03051 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/FlywayEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/FlywayEndpointTests.java @@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class FlywayEndpointTests extends AbstractEndpointTests { public FlywayEndpointTests() { - super(Config.class, FlywayEndpoint.class, "flyway", true, "endpoints.flyway"); + super(Config.class, FlywayEndpoint.class, "flyway", "endpoints.flyway"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/HealthEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/HealthEndpointTests.java index c81022f1c8c..766eb6cd5f6 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/HealthEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/HealthEndpointTests.java @@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class HealthEndpointTests extends AbstractEndpointTests { public HealthEndpointTests() { - super(Config.class, HealthEndpoint.class, "health", false, "endpoints.health"); + super(Config.class, HealthEndpoint.class, "health", "endpoints.health"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/InfoEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/InfoEndpointTests.java index 0566d32b03f..2181c6569b6 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/InfoEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/InfoEndpointTests.java @@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class InfoEndpointTests extends AbstractEndpointTests { public InfoEndpointTests() { - super(Config.class, InfoEndpoint.class, "info", false, "endpoints.info"); + super(Config.class, InfoEndpoint.class, "info", "endpoints.info"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LiquibaseEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LiquibaseEndpointTests.java index b4079f6600d..fefe552e9d1 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LiquibaseEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LiquibaseEndpointTests.java @@ -38,8 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class LiquibaseEndpointTests extends AbstractEndpointTests { public LiquibaseEndpointTests() { - super(Config.class, LiquibaseEndpoint.class, "liquibase", true, - "endpoints.liquibase"); + super(Config.class, LiquibaseEndpoint.class, "liquibase", "endpoints.liquibase"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LoggersEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LoggersEndpointTests.java index c93ae95d484..6a32926595e 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LoggersEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/LoggersEndpointTests.java @@ -44,7 +44,7 @@ import static org.mockito.Mockito.verify; public class LoggersEndpointTests extends AbstractEndpointTests { public LoggersEndpointTests() { - super(Config.class, LoggersEndpoint.class, "loggers", true, "endpoints.loggers"); + super(Config.class, LoggersEndpoint.class, "loggers", "endpoints.loggers"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java index c5840c4e554..9cb821f6a44 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/MetricsEndpointTests.java @@ -49,7 +49,7 @@ public class MetricsEndpointTests extends AbstractEndpointTests private Metric metric3 = new Metric<>("c", 3); public MetricsEndpointTests() { - super(Config.class, MetricsEndpoint.class, "metrics", true, "endpoints.metrics"); + super(Config.class, MetricsEndpoint.class, "metrics", "endpoints.metrics"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ShutdownEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ShutdownEndpointTests.java index 81cf5d4d66e..ae7e8d76620 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ShutdownEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/ShutdownEndpointTests.java @@ -42,8 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class ShutdownEndpointTests extends AbstractEndpointTests { public ShutdownEndpointTests() { - super(Config.class, ShutdownEndpoint.class, "shutdown", true, - "endpoints.shutdown"); + super(Config.class, ShutdownEndpoint.class, "shutdown", "endpoints.shutdown"); } @Override diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TraceEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TraceEndpointTests.java index e6ab9db4b1a..517d5f12073 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TraceEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/TraceEndpointTests.java @@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; public class TraceEndpointTests extends AbstractEndpointTests { public TraceEndpointTests() { - super(Config.class, TraceEndpoint.class, "trace", true, "endpoints.trace"); + super(Config.class, TraceEndpoint.class, "trace", "endpoints.trace"); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporterTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporterTests.java index e52666df67d..91136267fd6 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporterTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/jmx/EndpointMBeanExporterTests.java @@ -86,8 +86,8 @@ public class EndpointMBeanExporterTests { MBeanInfo mbeanInfo = mbeanExporter.getServer() .getMBeanInfo(getObjectName("endpoint1", this.context)); assertThat(mbeanInfo).isNotNull(); - assertThat(mbeanInfo.getOperations().length).isEqualTo(3); - assertThat(mbeanInfo.getAttributes().length).isEqualTo(3); + assertThat(mbeanInfo.getOperations().length).isEqualTo(2); + assertThat(mbeanInfo.getAttributes().length).isEqualTo(2); } @Test diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointTests.java index eb925246d91..6cfa7c70fe9 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointTests.java @@ -58,7 +58,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ @RunWith(SpringRunner.class) @SpringBootTest -@TestPropertySource(properties = { "info.app.name=MyService" }) +@TestPropertySource(properties = { "info.app.name=MyService", + "management.security.enabled=false" }) public class InfoMvcEndpointTests { @Autowired diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointWithNoInfoContributorsTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointWithNoInfoContributorsTests.java index 2246076a8e1..e2f0d044316 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointWithNoInfoContributorsTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/InfoMvcEndpointWithNoInfoContributorsTests.java @@ -34,6 +34,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -50,6 +51,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. */ @RunWith(SpringRunner.class) @SpringBootTest +@TestPropertySource(properties = "management.security.enabled=false") public class InfoMvcEndpointWithNoInfoContributorsTests { @Autowired diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointIntegrationTests.java index 45c8bb2a128..7b4ebdca967 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointIntegrationTests.java @@ -112,28 +112,7 @@ public class MvcEndpointIntegrationTests { } @Test - public void nonSensitiveEndpointsAreNotSecureByDefault() throws Exception { - this.context = new AnnotationConfigWebApplicationContext(); - this.context.register(SecureConfiguration.class); - MockMvc mockMvc = createSecureMockMvc(); - mockMvc.perform(get("/application/info")).andExpect(status().isOk()); - mockMvc.perform(get("/application")).andExpect(status().isOk()); - } - - @Test - public void nonSensitiveEndpointsAreNotSecureByDefaultWithCustomContextPath() - throws Exception { - this.context = new AnnotationConfigWebApplicationContext(); - this.context.register(SecureConfiguration.class); - TestPropertyValues.of("management.context-path:/management") - .applyTo(this.context); - MockMvc mockMvc = createSecureMockMvc(); - mockMvc.perform(get("/management/info")).andExpect(status().isOk()); - mockMvc.perform(get("/management")).andExpect(status().isOk()); - } - - @Test - public void sensitiveEndpointsAreSecureByDefault() throws Exception { + public void endpointsAreSecureByDefault() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); this.context.register(SecureConfiguration.class); MockMvc mockMvc = createSecureMockMvc(); @@ -141,8 +120,7 @@ public class MvcEndpointIntegrationTests { } @Test - public void sensitiveEndpointsAreSecureByDefaultWithCustomContextPath() - throws Exception { + public void endpointsAreSecureByDefaultWithCustomContextPath() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); this.context.register(SecureConfiguration.class); TestPropertyValues.of("management.context-path:/management") @@ -152,7 +130,7 @@ public class MvcEndpointIntegrationTests { } @Test - public void sensitiveEndpointsAreSecureWithNonActuatorRoleWithCustomContextPath() + public void endpointsAreSecureWithNonActuatorRoleWithCustomContextPath() throws Exception { TestSecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken("user", "N/A", "ROLE_USER")); @@ -165,7 +143,7 @@ public class MvcEndpointIntegrationTests { } @Test - public void sensitiveEndpointsAreSecureWithActuatorRoleWithCustomContextPath() + public void endpointsAreSecureWithActuatorRoleWithCustomContextPath() throws Exception { TestSecurityContextHolder.getContext().setAuthentication( new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR")); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptorTests.java index 167ccd35bed..aa2cb7274e0 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptorTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/MvcEndpointSecurityInterceptorTests.java @@ -89,22 +89,14 @@ public class MvcEndpointSecurityInterceptorTests { } @Test - public void endpointNotSensitiveShouldAllowAccess() throws Exception { - this.endpoint.setSensitive(false); - assertThat(this.securityInterceptor.preHandle(this.request, this.response, - this.handlerMethod)).isTrue(); - } - - @Test - public void sensitiveEndpointIfRoleIsPresentShouldAllowAccess() throws Exception { + public void endpointIfRoleIsPresentShouldAllowAccess() throws Exception { this.servletContext.declareRoles("SUPER_HERO"); assertThat(this.securityInterceptor.preHandle(this.request, this.response, this.handlerMethod)).isTrue(); } @Test - public void sensitiveEndpointIfNotAuthenticatedShouldNotAllowAccess() - throws Exception { + public void endpointIfNotAuthenticatedShouldNotAllowAccess() throws Exception { assertThat(this.securityInterceptor.preHandle(this.request, this.response, this.handlerMethod)).isFalse(); verify(this.response).sendError(HttpStatus.UNAUTHORIZED.value(), @@ -118,8 +110,7 @@ public class MvcEndpointSecurityInterceptorTests { } @Test - public void sensitiveEndpointIfRoleIsNotCorrectShouldNotAllowAccess() - throws Exception { + public void endpointIfRoleIsNotCorrectShouldNotAllowAccess() throws Exception { Principal principal = mock(Principal.class); this.request.setUserPrincipal(principal); this.servletContext.declareRoles("HERO"); @@ -130,8 +121,7 @@ public class MvcEndpointSecurityInterceptorTests { } @Test - public void sensitiveEndpointIfRoleNotCorrectShouldCheckAuthorities() - throws Exception { + public void endpointIfRoleNotCorrectShouldCheckAuthorities() throws Exception { Principal principal = mock(Principal.class); this.request.setUserPrincipal(principal); Authentication authentication = mock(Authentication.class); @@ -144,7 +134,7 @@ public class MvcEndpointSecurityInterceptorTests { } @Test - public void sensitiveEndpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess() + public void endpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess() throws Exception { Principal principal = mock(Principal.class); this.request.setUserPrincipal(principal); diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java index 95b2f3a46aa..b4b8aab099f 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityHealthMvcEndpointIntegrationTests.java @@ -16,8 +16,6 @@ package org.springframework.boot.actuate.endpoint.mvc; -import java.security.Principal; - import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; @@ -38,12 +36,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.mock.web.MockServletContext; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import static org.hamcrest.CoreMatchers.containsString; -import static org.mockito.Mockito.mock; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -65,19 +61,6 @@ public class NoSpringSecurityHealthMvcEndpointIntegrationTests { this.context.close(); } - @Test - public void healthWhenRightRoleNotPresentShouldNotExposeHealthDetails() - throws Exception { - this.context = new AnnotationConfigWebApplicationContext(); - this.context.setServletContext(new MockServletContext()); - this.context.register(TestConfiguration.class); - this.context.refresh(); - MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); - mockMvc.perform(get("/application/health").with(getRequestPostProcessor())) - .andExpect(status().isOk()) - .andExpect(content().string("{\"status\":\"UP\"}")); - } - @Test public void healthDetailPresent() throws Exception { this.context = new AnnotationConfigWebApplicationContext(); @@ -91,14 +74,6 @@ public class NoSpringSecurityHealthMvcEndpointIntegrationTests { "\"status\":\"UP\",\"test\":{\"status\":\"UP\",\"hello\":\"world\"}"))); } - private RequestPostProcessor getRequestPostProcessor() { - return (request) -> { - Principal principal = mock(Principal.class); - request.setUserPrincipal(principal); - return request; - }; - } - @ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class, EndpointWebMvcAutoConfiguration.class, diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityMvcEndpointSecurityInterceptorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityMvcEndpointSecurityInterceptorTests.java index 8db900cd0ad..b09383dadaa 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityMvcEndpointSecurityInterceptorTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/endpoint/mvc/NoSpringSecurityMvcEndpointSecurityInterceptorTests.java @@ -74,8 +74,7 @@ public class NoSpringSecurityMvcEndpointSecurityInterceptorTests { } @Test - public void sensitiveEndpointIfRoleNotPresentShouldNotValidateAuthorities() - throws Exception { + public void endpointIfRoleNotPresentShouldNotValidateAuthorities() throws Exception { Principal principal = mock(Principal.class); this.request.setUserPrincipal(principal); this.servletContext.declareRoles("HERO"); diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 6ce411df1c4..e85224d39d2 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -1084,86 +1084,66 @@ content into your application; rather pick only the properties that you need. # ENDPOINTS ({sc-spring-boot-actuator}/endpoint/AbstractEndpoint.{sc-ext}[AbstractEndpoint] subclasses) endpoints.enabled=true # Enable endpoints. - endpoints.sensitive= # Default endpoint sensitive setting. endpoints.auditevents.enabled= # Enable the endpoint. endpoints.auditevents.path= # Endpoint path. - endpoints.auditevents.sensitive=false # Enable security on the endpoint. endpoints.autoconfig.enabled= # Enable the endpoint. endpoints.autoconfig.id= # Endpoint identifier. endpoints.autoconfig.path= # Endpoint path. - endpoints.autoconfig.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.beans.enabled= # Enable the endpoint. endpoints.beans.id= # Endpoint identifier. endpoints.beans.path= # Endpoint path. - endpoints.beans.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.configprops.enabled= # Enable the endpoint. endpoints.configprops.id= # Endpoint identifier. endpoints.configprops.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. endpoints.configprops.path= # Endpoint path. - endpoints.configprops.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.docs.curies.enabled=false # Enable the curie generation. endpoints.docs.enabled=true # Enable actuator docs endpoint. endpoints.docs.path=/docs # - endpoints.docs.sensitive=false # endpoints.dump.enabled= # Enable the endpoint. endpoints.dump.id= # Endpoint identifier. endpoints.dump.path= # Endpoint path. - endpoints.dump.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.env.enabled= # Enable the endpoint. endpoints.env.id= # Endpoint identifier. endpoints.env.keys-to-sanitize=password,secret,key,token,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions. endpoints.env.path= # Endpoint path. - endpoints.env.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.flyway.enabled= # Enable the endpoint. endpoints.flyway.id= # Endpoint identifier. - endpoints.flyway.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.health.enabled= # Enable the endpoint. endpoints.health.id= # Endpoint identifier. endpoints.health.mapping.*= # Mapping of health statuses to HttpStatus codes. By default, registered health statuses map to sensible defaults (i.e. UP maps to 200). endpoints.health.path= # Endpoint path. - endpoints.health.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.health.time-to-live=1000 # Time to live for cached result, in milliseconds. endpoints.heapdump.enabled= # Enable the endpoint. endpoints.heapdump.path= # Endpoint path. - endpoints.heapdump.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.info.enabled= # Enable the endpoint. endpoints.info.id= # Endpoint identifier. endpoints.info.path= # Endpoint path. - endpoints.info.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.jolokia.enabled=true # Enable Jolokia endpoint. endpoints.jolokia.path=/jolokia # Endpoint URL path. - endpoints.jolokia.sensitive=true # Enable security on the endpoint. endpoints.liquibase.enabled= # Enable the endpoint. endpoints.liquibase.id= # Endpoint identifier. - endpoints.liquibase.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.logfile.enabled=true # Enable the endpoint. endpoints.logfile.external-file= # External Logfile to be accessed. endpoints.logfile.path=/logfile # Endpoint URL path. - endpoints.logfile.sensitive=true # Enable security on the endpoint. endpoints.loggers.enabled=true # Enable the endpoint. endpoints.loggers.id= # Endpoint identifier. endpoints.loggers.path=/logfile # Endpoint path. - endpoints.loggers.sensitive=true # Mark if the endpoint exposes sensitive information. endpoints.mappings.enabled= # Enable the endpoint. endpoints.mappings.id= # Endpoint identifier. endpoints.mappings.path= # Endpoint path. - endpoints.mappings.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.metrics.enabled= # Enable the endpoint. endpoints.metrics.filter.enabled=true # Enable the metrics servlet filter. endpoints.metrics.filter.gauge-submissions=merged # Http filter gauge submissions (merged, per-http-method) endpoints.metrics.filter.counter-submissions=merged # Http filter counter submissions (merged, per-http-method) endpoints.metrics.id= # Endpoint identifier. endpoints.metrics.path= # Endpoint path. - endpoints.metrics.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.shutdown.enabled= # Enable the endpoint. endpoints.shutdown.id= # Endpoint identifier. endpoints.shutdown.path= # Endpoint path. - endpoints.shutdown.sensitive= # Mark if the endpoint exposes sensitive information. endpoints.trace.enabled= # Enable the endpoint. endpoints.trace.filter.enabled=true # Enable the trace servlet filter. endpoints.trace.id= # Endpoint identifier. endpoints.trace.path= # Endpoint path. - endpoints.trace.sensitive= # Mark if the endpoint exposes sensitive information. # ENDPOINTS CORS CONFIGURATION ({sc-spring-boot-actuator}/autoconfigure/EndpointCorsProperties.{sc-ext}[EndpointCorsProperties]) endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported. diff --git a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc index 8550dafe17c..37c087357c6 100644 --- a/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc @@ -67,111 +67,142 @@ The following technology agnostic endpoints are available: [cols="2,5,1"] |=== -| ID | Description | Sensitive Default +| ID | Description |`auditevents` |Exposes audit events information for the current application. -|true |`autoconfig` |Displays an auto-configuration report showing all auto-configuration candidates and the reason why they '`were`' or '`were not`' applied. -|true |`beans` |Displays a complete list of all the Spring beans in your application. -|true |`configprops` |Displays a collated list of all `@ConfigurationProperties`. -|true |`dump` |Performs a thread dump. -|true |`env` |Exposes properties from Spring's `ConfigurableEnvironment`. -|true |`flyway` |Shows any Flyway database migrations that have been applied. -|true |`health` -|Shows application health information (when the application is secure, a simple '`status`' -when accessed over an unauthenticated connection or full message details when -authenticated). -|false +|Shows application health information. |`info` |Displays arbitrary application info. -|false |`loggers` |Shows and modifies the configuration of loggers in the application. -|true |`liquibase` |Shows any Liquibase database migrations that have been applied. -|true |`metrics` |Shows '`metrics`' information for the current application. -|true |`mappings` |Displays a collated list of all `@RequestMapping` paths. -|true |`shutdown` |Allows the application to be gracefully shutdown (not enabled by default). -|true |`trace` |Displays trace information (by default the last 100 HTTP requests). -|true |=== If you are using Spring MVC, the following additional endpoints can also be used: [cols="2,5,1"] |=== -| ID | Description | Sensitive Default +| ID | Description |`heapdump` |Returns a GZip compressed `hprof` heap dump file. -|true |`jolokia` |Exposes JMX beans over HTTP (when Jolokia is on the classpath). -|true |`logfile` |Returns the contents of the logfile (if `logging.file` or `logging.path` properties have been set). Supports the use of the HTTP `Range` header to retrieve part of the log file's content. -|true |=== -NOTE: Depending on how an endpoint is exposed, the `sensitive` property may be used as -a security hint. For example, sensitive endpoints will require a username/password when -they are accessed over HTTP (or simply disabled if web security is not enabled). +[[production-ready-endpoints-security]] +=== Securing endpoints +By default all HTTP endpoints are secured such that only users that have an `ACTUATOR` +role may access them. Security is enforced using the standard +`HttpServletRequest.isUserInRole` method. + +TIP: Use the `management.security.roles` property if you want something different to +`ACTUATOR`. + +If you are deploying applications behind a firewall, you may prefer that all your actuator +endpoints can be accessed without requiring authentication. You can do this by changing +the `management.security.enabled` property: + +.application.properties +[source,properties,indent=0] +---- + management.security.enabled=false +---- + +NOTE: By default, actuator endpoints are exposed on the same port that serves regular +HTTP traffic. Take care not to accidentally expose sensitive information if you change +the `management.security.enabled` property. + +If you're deploying applications publicly, you may want to add '`Spring Security`' to +handle user authentication. When '`Spring Security`' is added, by default '`basic`' +authentication will be used with the username `user` and a generated password (which is +printed on the console when the application starts). + +TIP: Generated passwords are logged as the application starts. Search for '`Using default +security password`'. + +You can use Spring properties to change the username and password and to change the +security role(s) required to access the endpoints. For example, you might set the following +in your `application.properties`: + +[source,properties,indent=0] +---- + security.user.name=admin + security.user.password=secret + management.security.roles=SUPERUSER +---- + +If your application has custom security configuration and you want all your actuator +endpoints to be accessible without authentication, you need to explicitly configure that +in your security configuration. Along with that, you need to change the +`management.security.enabled` property to `false`. + +If your custom security configuration secures your actuator endpoints, you also need to +ensure that the authenticated user has the roles specified under +`management.security.roles`. + +TIP: If you don't have a use case for exposing basic health information to unauthenticated +users, and you have secured the actuator endpoints with custom security, you can set +`management.security.enabled` to `false`. This will inform Spring Boot to skip the +additional role check. [[production-ready-customizing-endpoints]] === Customizing endpoints Endpoints can be customized using Spring properties. You can change if an endpoint is -`enabled`, if it is considered `sensitive` and even its `id`. +`enabled` and its `id`. -For example, here is an `application.properties` that changes the sensitivity and id -of the `beans` endpoint and also enables `shutdown`. +For example, here is an `application.properties` that changes the id of the `beans` +endpoint and also enables `shutdown`. [source,properties,indent=0] ---- endpoints.beans.id=springbeans - endpoints.beans.sensitive=false endpoints.shutdown.enabled=true ---- @@ -188,16 +219,6 @@ For example, the following will disable _all_ endpoints except for `info`: endpoints.info.enabled=true ---- -Likewise, you can also choose to globally set the "`sensitive`" flag of all endpoints. By -default, the sensitive flag depends on the type of endpoint (see the table above). -For example, to mark _all_ endpoints as sensitive except `info`: - -[source,properties,indent=0] ----- - endpoints.sensitive=true - endpoints.info.sensitive=false ----- - [[production-ready-endpoint-hypermedia]] @@ -272,12 +293,6 @@ overall health status. If no `HealthIndicator` returns a status that is known to === Security with HealthIndicators -Information returned by `HealthIndicators` is often somewhat sensitive in nature. For -example, you probably don't want to publish details of your database server to the -world. For this reason, by default, only the health status is exposed over an -unauthenticated HTTP connection. If you are happy for complete health information to always -be exposed you can set `endpoints.health.sensitive` to `false`. - Health responses are also cached to prevent "`denial of service`" attacks. Use the `endpoints.health.time-to-live` property if you want to change the default cache period of 1000 milliseconds. @@ -545,64 +560,6 @@ is exposed as `/application/health`. -[[production-ready-sensitive-endpoints]] -=== Accessing sensitive endpoints -By default all sensitive HTTP endpoints are secured such that only users that have an -`ACTUATOR` role may access them. Security is enforced using the standard -`HttpServletRequest.isUserInRole` method. - -TIP: Use the `management.security.roles` property if you want something different to -`ACTUATOR`. - -If you are deploying applications behind a firewall, you may prefer that all your actuator -endpoints can be accessed without requiring authentication. You can do this by changing -the `management.security.enabled` property: - -.application.properties -[source,properties,indent=0] ----- - management.security.enabled=false ----- - -NOTE: By default, actuator endpoints are exposed on the same port that serves regular -HTTP traffic. Take care not to accidentally expose sensitive information if you change -the `management.security.enabled` property. - -If you're deploying applications publicly, you may want to add '`Spring Security`' to -handle user authentication. When '`Spring Security`' is added, by default '`basic`' -authentication will be used with the username `user` and a generated password (which is -printed on the console when the application starts). - -TIP: Generated passwords are logged as the application starts. Search for '`Using default -security password`'. - -You can use Spring properties to change the username and password and to change the -security role(s) required to access the endpoints. For example, you might set the following -in your `application.properties`: - -[source,properties,indent=0] ----- - security.user.name=admin - security.user.password=secret - management.security.roles=SUPERUSER ----- - -If your application has custom security configuration and you want all your actuator endpoints -to be accessible without authentication, you need to explicitly configure that in your -security configuration. Along with that, you need to change the `management.security.enabled` -property to `false`. - -If your custom security configuration secures your actuator endpoints, you also need to ensure that -the authenticated user has the roles specified under `management.security.roles`. - -TIP: If you don't have a use case for exposing basic health information to unauthenticated users, -and you have secured the actuator endpoints with custom security, you can set `management.security.enabled` -to `false`. This will inform Spring Boot to skip the additional role check. - - - - - [[production-ready-customizing-management-server-context-path]] === Customizing the management endpoint paths Sometimes it is useful to customize the prefix for the management endpoints. @@ -763,7 +720,7 @@ Sample summarized HTTP response for status "DOWN" (notice the 503 status code): {"status":"DOWN"} ---- -Sample detailed HTTP response: +Sample detailed HTTP response: [source,indent=0] ---- @@ -789,30 +746,6 @@ Sample detailed HTTP response: } ---- -The above-described restrictions can be enhanced, thereby allowing only authenticated -users full access to the health endpoint in a secure application. To do so, set -`endpoints.health.sensitive` to `true`. Here's a summary of behavior (with default -`sensitive` flag value "`false`" indicated in bold): - -|==== -| `management.security.enabled` | `endpoints.health.sensitive` | Unauthenticated | Authenticated (with right role) - -|false -|* -|Full content -|Full content - -|true -|**false** -|Status only -|Full content - -|true -|true -|No content -|Full content -|==== - [[production-ready-jmx]] diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/CorsSampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/CorsSampleActuatorApplicationTests.java index bf6cfce43d8..aa08a14eaad 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/CorsSampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/CorsSampleActuatorApplicationTests.java @@ -50,14 +50,14 @@ public class CorsSampleActuatorApplicationTests { } @Test - public void sensitiveEndpointShouldReturnUnauthorized() throws Exception { + public void endpointShouldReturnUnauthorized() throws Exception { ResponseEntity entity = this.testRestTemplate.getForEntity("/application/env", Map.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test - public void preflightRequestForInsensitiveShouldReturnOk() throws Exception { + public void preflightRequestToEndpointShouldReturnOk() throws Exception { RequestEntity healthRequest = RequestEntity .options(new URI("/application/health")) .header("Origin", "http://localhost:8080") @@ -67,15 +67,6 @@ public class CorsSampleActuatorApplicationTests { assertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK); } - @Test - public void preflightRequestForSensitiveEndpointShouldReturnOk() throws Exception { - RequestEntity entity = RequestEntity.options(new URI("/application/env")) - .header("Origin", "http://localhost:8080") - .header("Access-Control-Request-Method", "GET").build(); - ResponseEntity env = this.testRestTemplate.exchange(entity, Map.class); - assertThat(env.getStatusCode()).isEqualTo(HttpStatus.OK); - } - @Test public void preflightRequestWhenCorsConfigInvalidShouldReturnForbidden() throws Exception { diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementAddressActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementAddressActuatorApplicationTests.java index 0ea134ae89c..4f692692539 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementAddressActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementAddressActuatorApplicationTests.java @@ -21,7 +21,9 @@ import java.util.Map; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.autoconfigure.LocalManagementPort; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -45,6 +47,9 @@ import static org.assertj.core.api.Assertions.assertThat; @DirtiesContext public class ManagementAddressActuatorApplicationTests { + @Autowired + private SecurityProperties security; + @LocalServerPort private int port = 9010; @@ -61,11 +66,16 @@ public class ManagementAddressActuatorApplicationTests { @Test public void testHealth() throws Exception { - ResponseEntity entity = new TestRestTemplate().getForEntity( - "http://localhost:" + this.managementPort + "/admin/health", - String.class); + ResponseEntity entity = new TestRestTemplate() + .withBasicAuth("user", getPassword()) + .getForEntity("http://localhost:" + this.managementPort + "/admin/health", + String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } + private String getPassword() { + return this.security.getUser().getPassword(); + } + } diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPathSampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPathSampleActuatorApplicationTests.java index c7db62b77f3..76a84289ec4 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPathSampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPathSampleActuatorApplicationTests.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -46,10 +47,14 @@ public class ManagementPathSampleActuatorApplicationTests { @Autowired private TestRestTemplate restTemplate; + @Autowired + private SecurityProperties securityProperties; + @Test public void testHealth() throws Exception { - ResponseEntity entity = this.restTemplate.getForEntity("/admin/health", - String.class); + ResponseEntity entity = this.restTemplate + .withBasicAuth("user", getPassword()) + .getForEntity("/admin/health", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } @@ -65,4 +70,8 @@ public class ManagementPathSampleActuatorApplicationTests { assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie"); } + private String getPassword() { + return this.securityProperties.getUser().getPassword(); + } + } diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortAndPathSampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortAndPathSampleActuatorApplicationTests.java index 030e7263b36..24ed3260a35 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortAndPathSampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortAndPathSampleActuatorApplicationTests.java @@ -77,9 +77,10 @@ public class ManagementPortAndPathSampleActuatorApplicationTests { @Test public void testHealth() throws Exception { - ResponseEntity entity = new TestRestTemplate().getForEntity( - "http://localhost:" + this.managementPort + "/admin/health", - String.class); + ResponseEntity entity = new TestRestTemplate() + .withBasicAuth("user", getPassword()) + .getForEntity("http://localhost:" + this.managementPort + "/admin/health", + String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortSampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortSampleActuatorApplicationTests.java index 6084e28b7f3..03ee928fd78 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortSampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ManagementPortSampleActuatorApplicationTests.java @@ -71,14 +71,17 @@ public class ManagementPortSampleActuatorApplicationTests { testHome(); // makes sure some requests have been made @SuppressWarnings("rawtypes") ResponseEntity entity = new TestRestTemplate().getForEntity( - "http://localhost:" + this.managementPort + "/application/metrics", Map.class); + "http://localhost:" + this.managementPort + "/application/metrics", + Map.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test public void testHealth() throws Exception { - ResponseEntity entity = new TestRestTemplate().getForEntity( - "http://localhost:" + this.managementPort + "/application/health", String.class); + ResponseEntity entity = new TestRestTemplate() + .withBasicAuth("user", getPassword()).getForEntity( + "http://localhost:" + this.managementPort + "/application/health", + String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/NonSensitiveHealthTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/NonSensitiveHealthTests.java deleted file mode 100644 index 9520f42c6a0..00000000000 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/NonSensitiveHealthTests.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 sample.actuator; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for /health with {@code endpoints.health.sensitive=false}. - * - * @author Phillip Webb - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { - "endpoints.health.sensitive=false" }) -@DirtiesContext -public class NonSensitiveHealthTests { - - @Autowired - private TestRestTemplate restTemplate; - - @Test - public void testSecureHealth() throws Exception { - ResponseEntity entity = this.restTemplate.getForEntity("/application/health", - String.class); - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getBody()).doesNotContain("\"hello\":1"); - } - -} diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/SampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/SampleActuatorApplicationTests.java index 1e9a9fd63b6..7c126fd5390 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/SampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/SampleActuatorApplicationTests.java @@ -121,24 +121,17 @@ public class SampleActuatorApplicationTests { @Test public void testHealth() throws Exception { ResponseEntity entity = this.restTemplate + .withBasicAuth("user", getPassword()) .getForEntity("/application/health", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); assertThat(entity.getBody()).doesNotContain("\"hello\":\"1\""); } - @Test - public void testSecureHealth() throws Exception { - ResponseEntity entity = this.restTemplate - .withBasicAuth("user", getPassword()) - .getForEntity("/application/health", String.class); - assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(entity.getBody()).contains("\"hello\":1"); - } - @Test public void testInfo() throws Exception { ResponseEntity entity = this.restTemplate + .withBasicAuth("user", getPassword()) .getForEntity("/application/info", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()) diff --git a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ServletPathSampleActuatorApplicationTests.java b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ServletPathSampleActuatorApplicationTests.java index 31bbc9bdaac..8515586d94a 100644 --- a/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ServletPathSampleActuatorApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-actuator/src/test/java/sample/actuator/ServletPathSampleActuatorApplicationTests.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.boot.test.web.client.TestRestTemplate; @@ -46,6 +47,9 @@ public class ServletPathSampleActuatorApplicationTests { @Autowired private TestRestTemplate restTemplate; + @Autowired + private SecurityProperties security; + @Test public void testErrorPath() throws Exception { @SuppressWarnings("rawtypes") @@ -60,8 +64,9 @@ public class ServletPathSampleActuatorApplicationTests { @Test public void testHealth() throws Exception { - ResponseEntity entity = this.restTemplate.getForEntity("/spring//application/health", - String.class); + ResponseEntity entity = this.restTemplate + .withBasicAuth("user", getPassword()) + .getForEntity("/spring/application/health", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } @@ -78,4 +83,8 @@ public class ServletPathSampleActuatorApplicationTests { assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie"); } + private String getPassword() { + return this.security.getUser().getPassword(); + } + }