Support global endpoint.sensitive override
Add support for an `endpoint.sensitive` property that can be used to override the endpoint `sensitive` default. Fixes gh-4419
This commit is contained in:
@@ -35,6 +35,7 @@ import org.springframework.boot.actuate.endpoint.BeansEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.ConfigurationPropertiesReportEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.DumpEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointProperties;
|
||||
import org.springframework.boot.actuate.endpoint.EnvironmentEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.FlywayEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.HealthEndpoint;
|
||||
@@ -60,6 +61,7 @@ import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
|
||||
import org.springframework.boot.bind.PropertiesConfigurationFactory;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
@@ -82,6 +84,7 @@ import org.springframework.web.servlet.handler.AbstractHandlerMethodMapping;
|
||||
*/
|
||||
@Configuration
|
||||
@AutoConfigureAfter({ FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class })
|
||||
@EnableConfigurationProperties(EndpointProperties.class)
|
||||
public class EndpointAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -31,8 +31,6 @@ import org.springframework.core.env.Environment;
|
||||
*/
|
||||
public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAware {
|
||||
|
||||
private static final String ENDPOINTS_ENABLED_PROPERTY = "endpoints.enabled";
|
||||
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
@@ -43,10 +41,12 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||
@Pattern(regexp = "\\w+", message = "ID must only contains letters, numbers and '_'")
|
||||
private String id;
|
||||
|
||||
private final boolean sensitiveDefaut;
|
||||
|
||||
/**
|
||||
* Mark if the endpoint exposes sensitive information.
|
||||
*/
|
||||
private boolean sensitive;
|
||||
private Boolean sensitive;
|
||||
|
||||
/**
|
||||
* Enable the endpoint.
|
||||
@@ -66,11 +66,11 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||
* Create a new endpoint instance. The enpoint 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
|
||||
* @param sensitive if the endpoint is sensitive by default
|
||||
*/
|
||||
public AbstractEndpoint(String id, boolean sensitive) {
|
||||
this.id = id;
|
||||
this.sensitive = sensitive;
|
||||
this.sensitiveDefaut = sensitive;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||
*/
|
||||
public AbstractEndpoint(String id, boolean sensitive, boolean enabled) {
|
||||
this.id = id;
|
||||
this.sensitive = sensitive;
|
||||
this.sensitiveDefaut = sensitive;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@@ -105,14 +105,7 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
if (this.enabled != null) {
|
||||
return this.enabled;
|
||||
}
|
||||
if (this.environment != null) {
|
||||
return this.environment.getProperty(ENDPOINTS_ENABLED_PROPERTY, Boolean.class,
|
||||
true);
|
||||
}
|
||||
return true;
|
||||
return EndpointProperties.isEnabled(this.environment, this.enabled);
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
@@ -121,10 +114,11 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
return EndpointProperties.isSensitive(this.environment, this.sensitive,
|
||||
this.sensitiveDefaut);
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
public void setSensitive(Boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.endpoint;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Global endpoint properties.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "endpoints")
|
||||
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;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
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.
|
||||
* @param environment the Spring environment or {@code null}.
|
||||
* @param enabled the endpoint property or {@code null}
|
||||
* @return if the endpoint is enabled
|
||||
*/
|
||||
public static boolean isEnabled(Environment environment, Boolean enabled) {
|
||||
if (enabled != null) {
|
||||
return enabled;
|
||||
}
|
||||
if (environment != null
|
||||
&& environment.containsProperty(ENDPOINTS_ENABLED_PROPERTY)) {
|
||||
return environment.getProperty(ENDPOINTS_ENABLED_PROPERTY, Boolean.class);
|
||||
}
|
||||
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 sensitiveDefaut 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 sensitiveDefaut) {
|
||||
if (sensitive != null) {
|
||||
return sensitive;
|
||||
}
|
||||
if (environment != null
|
||||
&& environment.containsProperty(ENDPOINTS_SENSITIVE_PROPERTY)) {
|
||||
return environment.getProperty(ENDPOINTS_SENSITIVE_PROPERTY, Boolean.class);
|
||||
}
|
||||
return sensitiveDefaut;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,10 @@
|
||||
package org.springframework.boot.actuate.endpoint.mvc;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
@@ -30,10 +33,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties("endpoints.docs")
|
||||
public class DocsMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEndpoint {
|
||||
public class DocsMvcEndpoint extends WebMvcConfigurerAdapter
|
||||
implements MvcEndpoint, EnvironmentAware {
|
||||
|
||||
private static final String DOCS_LOCATION = "classpath:/META-INF/resources/spring-boot-actuator/docs/";
|
||||
|
||||
private Environment environment;
|
||||
|
||||
private String path = "/docs";
|
||||
|
||||
/**
|
||||
@@ -44,12 +50,17 @@ public class DocsMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEndpo
|
||||
/**
|
||||
* Mark if the endpoint exposes sensitive information.
|
||||
*/
|
||||
private boolean sensitive;
|
||||
private Boolean sensitive;
|
||||
|
||||
private final ManagementServletContext managementServletContext;
|
||||
|
||||
private Curies curies = new Curies();
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public Curies getCuries() {
|
||||
return this.curies;
|
||||
}
|
||||
@@ -96,10 +107,10 @@ public class DocsMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEndpo
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
return EndpointProperties.isSensitive(this.environment, this.sensitive, false);
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
public void setSensitive(Boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -37,7 +40,10 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@ConfigurationProperties("endpoints.actuator")
|
||||
public class HalJsonMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEndpoint {
|
||||
public class HalJsonMvcEndpoint extends WebMvcConfigurerAdapter
|
||||
implements MvcEndpoint, EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Endpoint URL path.
|
||||
@@ -54,7 +60,7 @@ public class HalJsonMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEn
|
||||
/**
|
||||
* Mark if the endpoint exposes sensitive information.
|
||||
*/
|
||||
private boolean sensitive = false;
|
||||
private Boolean sensitive;
|
||||
|
||||
private final ManagementServletContext managementServletContext;
|
||||
|
||||
@@ -63,6 +69,11 @@ public class HalJsonMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEn
|
||||
this.path = getDefaultPath(managementServletContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
private String getDefaultPath(ManagementServletContext managementServletContext) {
|
||||
if (StringUtils.hasText(managementServletContext.getContextPath())) {
|
||||
return "";
|
||||
@@ -95,10 +106,10 @@ public class HalJsonMvcEndpoint extends WebMvcConfigurerAdapter implements MvcEn
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
return EndpointProperties.isSensitive(this.environment, this.sensitive, false);
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
public void setSensitive(Boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,12 @@ import org.jolokia.http.AgentServlet;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
@@ -48,7 +51,9 @@ import org.springframework.web.util.UrlPathHelper;
|
||||
@ConfigurationProperties(prefix = "endpoints.jolokia", ignoreUnknownFields = false)
|
||||
@HypermediaDisabled
|
||||
public class JolokiaMvcEndpoint implements MvcEndpoint, InitializingBean,
|
||||
ApplicationContextAware, ServletContextAware {
|
||||
ApplicationContextAware, ServletContextAware, EnvironmentAware {
|
||||
|
||||
private Environment environment;
|
||||
|
||||
/**
|
||||
* Endpoint URL path.
|
||||
@@ -65,7 +70,7 @@ public class JolokiaMvcEndpoint implements MvcEndpoint, InitializingBean,
|
||||
/**
|
||||
* Mark if the endpoint exposes sensitive information.
|
||||
*/
|
||||
private boolean sensitive = true;
|
||||
private Boolean sensitive;
|
||||
|
||||
private final ServletWrappingController controller = new ServletWrappingController();
|
||||
|
||||
@@ -94,6 +99,11 @@ public class JolokiaMvcEndpoint implements MvcEndpoint, InitializingBean,
|
||||
this.controller.setApplicationContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@@ -104,10 +114,10 @@ public class JolokiaMvcEndpoint implements MvcEndpoint, InitializingBean,
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
return EndpointProperties.isSensitive(this.environment, this.sensitive, true);
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
public void setSensitive(Boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.boot.actuate.endpoint.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.boot.logging.LogFile;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
@@ -67,7 +68,7 @@ public class LogFileMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
||||
/**
|
||||
* Mark if the endpoint exposes sensitive information.
|
||||
*/
|
||||
private boolean sensitive = true;
|
||||
private Boolean sensitive;
|
||||
|
||||
private Environment environment;
|
||||
|
||||
@@ -95,10 +96,10 @@ public class LogFileMvcEndpoint implements MvcEndpoint, EnvironmentAware {
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.sensitive;
|
||||
return EndpointProperties.isSensitive(this.environment, this.sensitive, true);
|
||||
}
|
||||
|
||||
public void setSensitive(boolean sensitive) {
|
||||
public void setSensitive(Boolean sensitive) {
|
||||
this.sensitive = sensitive;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
{"properties": [
|
||||
{
|
||||
"name": "endpoints.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Enable endpoints.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "endpoints.configprops.keys-to-sanitize",
|
||||
"type": "java.lang.String[]",
|
||||
|
||||
@@ -108,6 +108,19 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
assertThat(getEndpointBean().isSensitive(), equalTo(!this.sensitive));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSensitiveOverrideWithGlobal() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
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(), equalTo(!this.sensitive));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEnabledByDefault() throws Exception {
|
||||
assertThat(getEndpointBean().isEnabled(), equalTo(true));
|
||||
@@ -169,6 +182,26 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
.<String, Object>singletonMap("endpoints.sensitive", sensitive));
|
||||
this.context.getEnvironment().getPropertySources().addFirst(propertySource);
|
||||
this.context.register(this.configClass);
|
||||
this.context.refresh();
|
||||
assertThat(getEndpointBean().isSensitive(), equalTo(sensitive));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T getEndpointBean() {
|
||||
return (T) this.context.getBean(this.type);
|
||||
|
||||
@@ -724,6 +724,8 @@ 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.actuator.enabled=true # Enable the endpoint.
|
||||
endpoints.actuator.path= # Endpoint URL path.
|
||||
endpoints.actuator.sensitive=false # Enable security on the endpoint.
|
||||
@@ -744,7 +746,6 @@ content into your application; rather pick only the properties that you need.
|
||||
endpoints.dump.enabled= # Enable the endpoint.
|
||||
endpoints.dump.id= # Endpoint identifier.
|
||||
endpoints.dump.sensitive= # Mark if the endpoint exposes sensitive information.
|
||||
endpoints.enabled=true # Enable endpoints.
|
||||
endpoints.env.enabled= # Enable the endpoint.
|
||||
endpoints.env.id= # Endpoint identifier.
|
||||
endpoints.env.keys-to-sanitize=password,secret,key,.*credentials.*,vcap_services # Keys that should be sanitized. Keys can be simple strings that the property ends with or regex expressions.
|
||||
|
||||
@@ -65,7 +65,7 @@ The following endpoints are available:
|
||||
|
||||
[cols="2,5,1"]
|
||||
|===
|
||||
| ID | Description | Sensitive
|
||||
| ID | Description | Sensitive Default
|
||||
|
||||
|`actuator`
|
||||
|Provides a hypermedia-based "`discovery page`" for the other endpoints. Requires Spring
|
||||
@@ -166,6 +166,18 @@ 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]]
|
||||
=== Hypermedia for actuator MVC endpoints
|
||||
If http://projects.spring.io/spring-hateoas[Spring HATEOAS] is on the classpath (e.g.
|
||||
|
||||
Reference in New Issue
Block a user