mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Remove concept of sensitivity from Actuator's endpoints
Closes gh-9924
This commit is contained in:
parent
847f6d1b2c
commit
bb55f49396
@ -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).
|
||||
* <p>
|
||||
* 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<HttpSecurity>.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<? extends MvcEndpoint> endpoints = endpointHandlerMapping.getEndpoints();
|
||||
Set<String> 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,
|
||||
|
@ -41,7 +41,7 @@ class CloudFoundryDiscoveryMvcEndpoint extends AbstractMvcEndpoint {
|
||||
private final Set<NamedMvcEndpoint> endpoints;
|
||||
|
||||
CloudFoundryDiscoveryMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
||||
super("", false);
|
||||
super("");
|
||||
this.endpoints = endpoints;
|
||||
}
|
||||
|
||||
|
@ -41,47 +41,27 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, 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<T> implements Endpoint<T>, 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,13 +42,6 @@ public interface Endpoint<T> {
|
||||
*/
|
||||
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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class HealthEndpoint extends AbstractEndpoint<Health> {
|
||||
*/
|
||||
public HealthEndpoint(HealthAggregator healthAggregator,
|
||||
Map<String, HealthIndicator> 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(
|
||||
|
@ -41,7 +41,7 @@ public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||
* @param infoContributors the info contributors to use
|
||||
*/
|
||||
public InfoEndpoint(List<InfoContributor> infoContributors) {
|
||||
super("info", false);
|
||||
super("info");
|
||||
Assert.notNull(infoContributors, "Info contributors must not be null");
|
||||
this.infoContributors = infoContributors;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>>
|
||||
* Create a new {@link ShutdownEndpoint} instance.
|
||||
*/
|
||||
public ShutdownEndpoint() {
|
||||
super("shutdown", true, false);
|
||||
super("shutdown", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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());
|
||||
|
@ -80,11 +80,6 @@ public abstract class AbstractEndpointMvcAdapter<E extends Endpoint<?>>
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return this.delegate.isSensitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class<? extends Endpoint> getEndpointType() {
|
||||
|
@ -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<? extends Endpoint> getEndpointType() {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public class EndpointHandlerMapping extends AbstractEndpointHandlerMapping<MvcEn
|
||||
private final Set<NamedMvcEndpoint> endpoints;
|
||||
|
||||
private EndpointLinksMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
||||
super("", false);
|
||||
super("");
|
||||
this.endpoints = endpoints;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class HeapdumpMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||
}
|
||||
|
||||
protected HeapdumpMvcEndpoint(long timeout) {
|
||||
super("heapdump", "/heapdump", true);
|
||||
super("heapdump", "/heapdump");
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||
private File externalFile;
|
||||
|
||||
public LogFileMvcEndpoint() {
|
||||
super("logfile", "/logfile", true);
|
||||
super("logfile", "/logfile");
|
||||
}
|
||||
|
||||
public File getExternalFile() {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
||||
public static class ManagedEndpoint extends AbstractEndpoint<Boolean> {
|
||||
|
||||
public ManagedEndpoint() {
|
||||
super("managed", true);
|
||||
super("managed");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -200,7 +200,7 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
||||
class Nested extends AbstractEndpoint<Boolean> {
|
||||
|
||||
Nested() {
|
||||
super("managed", true);
|
||||
super("managed");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -867,11 +867,6 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
return "/endpoint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSensitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Class<? extends Endpoint> getEndpointType() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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\""));
|
||||
|
@ -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();
|
||||
|
@ -49,16 +49,13 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||
|
||||
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<T extends Endpoint<?>> {
|
||||
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<T extends Endpoint<?>> {
|
||||
assertThat(getEndpointBean().getId()).isEqualTo("myid");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSensitiveOverride() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
PropertySource<?> propertySource = new MapPropertySource("test",
|
||||
Collections.<String, Object>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<String, Object> 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<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()).isEqualTo(sensitive);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T getEndpointBean() {
|
||||
return (T) this.context.getBean(this.type);
|
||||
|
@ -47,7 +47,7 @@ public class AutoConfigurationReportEndpointTests
|
||||
extends AbstractEndpointTests<AutoConfigurationReportEndpoint> {
|
||||
|
||||
public AutoConfigurationReportEndpointTests() {
|
||||
super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig", true,
|
||||
super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig",
|
||||
"endpoints.autoconfig");
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class BeansEndpointTests extends AbstractEndpointTests<BeansEndpoint> {
|
||||
|
||||
public BeansEndpointTests() {
|
||||
super(Config.class, BeansEndpoint.class, "beans", true, "endpoints.beans");
|
||||
super(Config.class, BeansEndpoint.class, "beans", "endpoints.beans");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -43,7 +43,7 @@ public class ConfigurationPropertiesReportEndpointTests
|
||||
|
||||
public ConfigurationPropertiesReportEndpointTests() {
|
||||
super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops",
|
||||
true, "endpoints.configprops");
|
||||
"endpoints.configprops");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -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<DumpEndpoint> {
|
||||
|
||||
public DumpEndpointTests() {
|
||||
super(Config.class, DumpEndpoint.class, "dump", true, "endpoints.dump");
|
||||
super(Config.class, DumpEndpoint.class, "dump", "endpoints.dump");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentEndpoint> {
|
||||
|
||||
public EnvironmentEndpointTests() {
|
||||
super(Config.class, EnvironmentEndpoint.class, "env", true, "endpoints.env");
|
||||
super(Config.class, EnvironmentEndpoint.class, "env", "endpoints.env");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class FlywayEndpointTests extends AbstractEndpointTests<FlywayEndpoint> {
|
||||
|
||||
public FlywayEndpointTests() {
|
||||
super(Config.class, FlywayEndpoint.class, "flyway", true, "endpoints.flyway");
|
||||
super(Config.class, FlywayEndpoint.class, "flyway", "endpoints.flyway");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
|
||||
|
||||
public HealthEndpointTests() {
|
||||
super(Config.class, HealthEndpoint.class, "health", false, "endpoints.health");
|
||||
super(Config.class, HealthEndpoint.class, "health", "endpoints.health");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class InfoEndpointTests extends AbstractEndpointTests<InfoEndpoint> {
|
||||
|
||||
public InfoEndpointTests() {
|
||||
super(Config.class, InfoEndpoint.class, "info", false, "endpoints.info");
|
||||
super(Config.class, InfoEndpoint.class, "info", "endpoints.info");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -38,8 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class LiquibaseEndpointTests extends AbstractEndpointTests<LiquibaseEndpoint> {
|
||||
|
||||
public LiquibaseEndpointTests() {
|
||||
super(Config.class, LiquibaseEndpoint.class, "liquibase", true,
|
||||
"endpoints.liquibase");
|
||||
super(Config.class, LiquibaseEndpoint.class, "liquibase", "endpoints.liquibase");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -44,7 +44,7 @@ import static org.mockito.Mockito.verify;
|
||||
public class LoggersEndpointTests extends AbstractEndpointTests<LoggersEndpoint> {
|
||||
|
||||
public LoggersEndpointTests() {
|
||||
super(Config.class, LoggersEndpoint.class, "loggers", true, "endpoints.loggers");
|
||||
super(Config.class, LoggersEndpoint.class, "loggers", "endpoints.loggers");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -49,7 +49,7 @@ public class MetricsEndpointTests extends AbstractEndpointTests<MetricsEndpoint>
|
||||
private Metric<Number> 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
|
||||
|
@ -42,8 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class ShutdownEndpointTests extends AbstractEndpointTests<ShutdownEndpoint> {
|
||||
|
||||
public ShutdownEndpointTests() {
|
||||
super(Config.class, ShutdownEndpoint.class, "shutdown", true,
|
||||
"endpoints.shutdown");
|
||||
super(Config.class, ShutdownEndpoint.class, "shutdown", "endpoints.shutdown");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class TraceEndpointTests extends AbstractEndpointTests<TraceEndpoint> {
|
||||
|
||||
public TraceEndpointTests() {
|
||||
super(Config.class, TraceEndpoint.class, "trace", true, "endpoints.trace");
|
||||
super(Config.class, TraceEndpoint.class, "trace", "endpoints.trace");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"));
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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.
|
||||
|
@ -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]]
|
||||
|
@ -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 {
|
||||
|
@ -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<String> entity = new TestRestTemplate().getForEntity(
|
||||
"http://localhost:" + this.managementPort + "/admin/health",
|
||||
String.class);
|
||||
ResponseEntity<String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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<String> entity = this.restTemplate.getForEntity("/admin/health",
|
||||
String.class);
|
||||
ResponseEntity<String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -77,9 +77,10 @@ public class ManagementPortAndPathSampleActuatorApplicationTests {
|
||||
|
||||
@Test
|
||||
public void testHealth() throws Exception {
|
||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
|
||||
"http://localhost:" + this.managementPort + "/admin/health",
|
||||
String.class);
|
||||
ResponseEntity<String> 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\"");
|
||||
}
|
||||
|
@ -71,14 +71,17 @@ public class ManagementPortSampleActuatorApplicationTests {
|
||||
testHome(); // makes sure some requests have been made
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> 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<String> entity = new TestRestTemplate().getForEntity(
|
||||
"http://localhost:" + this.managementPort + "/application/health", String.class);
|
||||
ResponseEntity<String> 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\"");
|
||||
}
|
||||
|
@ -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<String> entity = this.restTemplate.getForEntity("/application/health",
|
||||
String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).doesNotContain("\"hello\":1");
|
||||
}
|
||||
|
||||
}
|
@ -121,24 +121,17 @@ public class SampleActuatorApplicationTests {
|
||||
@Test
|
||||
public void testHealth() throws Exception {
|
||||
ResponseEntity<String> 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<String> 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<String> entity = this.restTemplate
|
||||
.withBasicAuth("user", getPassword())
|
||||
.getForEntity("/application/info", String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody())
|
||||
|
@ -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<String> entity = this.restTemplate.getForEntity("/spring//application/health",
|
||||
String.class);
|
||||
ResponseEntity<String> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user