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 javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.beans.factory.ObjectProvider;
|
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.EndpointHandlerMapping;
|
||||||
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
|
||||||
import org.springframework.boot.actuate.endpoint.mvc.NamedMvcEndpoint;
|
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.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
|
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.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
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.
|
* {@link EnableAutoConfiguration Auto-configuration} for security of framework endpoints.
|
||||||
* Many aspects of the behavior can be controller with {@link ManagementServerProperties}
|
* 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
|
* via externalized application properties (or via an bean definition of that type to set
|
||||||
* the defaults).
|
* 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.
|
|
||||||
*
|
*
|
||||||
* @author Dave Syer
|
* @author Dave Syer
|
||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
|
|
@ -126,7 +120,6 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
.getRequestMatcher(this.contextResolver);
|
.getRequestMatcher(this.contextResolver);
|
||||||
configurer.requestMatchers(requestMatcher);
|
configurer.requestMatchers(requestMatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -223,8 +216,6 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
http.exceptionHandling().authenticationEntryPoint(entryPoint);
|
http.exceptionHandling().authenticationEntryPoint(entryPoint);
|
||||||
// Match all the requests for actuator endpoints ...
|
// Match all the requests for actuator endpoints ...
|
||||||
http.requestMatcher(matcher);
|
http.requestMatcher(matcher);
|
||||||
// ... but permitAll() for the non-sensitive ones
|
|
||||||
configurePermittedRequests(http.authorizeRequests());
|
|
||||||
http.httpBasic().authenticationEntryPoint(entryPoint).and().cors();
|
http.httpBasic().authenticationEntryPoint(entryPoint).and().cors();
|
||||||
// No cookies for management endpoints by default
|
// No cookies for management endpoints by default
|
||||||
http.csrf().disable();
|
http.csrf().disable();
|
||||||
|
|
@ -258,38 +249,9 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
return entryPoint;
|
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 static class EndpointPaths {
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) {
|
public String[] getPaths(EndpointHandlerMapping endpointHandlerMapping) {
|
||||||
if (endpointHandlerMapping == null) {
|
if (endpointHandlerMapping == null) {
|
||||||
|
|
@ -298,7 +260,6 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
Set<? extends MvcEndpoint> endpoints = endpointHandlerMapping.getEndpoints();
|
Set<? extends MvcEndpoint> endpoints = endpointHandlerMapping.getEndpoints();
|
||||||
Set<String> paths = new LinkedHashSet<>(endpoints.size());
|
Set<String> paths = new LinkedHashSet<>(endpoints.size());
|
||||||
for (MvcEndpoint endpoint : endpoints) {
|
for (MvcEndpoint endpoint : endpoints) {
|
||||||
if (isIncluded(endpoint)) {
|
|
||||||
String path = endpointHandlerMapping.getPath(endpoint.getPath());
|
String path = endpointHandlerMapping.getPath(endpoint.getPath());
|
||||||
paths.add(path);
|
paths.add(path);
|
||||||
if (!path.equals("")) {
|
if (!path.equals("")) {
|
||||||
|
|
@ -308,14 +269,9 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
}
|
}
|
||||||
paths.add(path + "/");
|
paths.add(path + "/");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return paths.toArray(new String[paths.size()]);
|
return paths.toArray(new String[paths.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean isIncluded(MvcEndpoint endpoint) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LazyEndpointPathRequestMatcher implements RequestMatcher {
|
private static class LazyEndpointPathRequestMatcher implements RequestMatcher {
|
||||||
|
|
@ -342,7 +298,8 @@ public class ManagementWebSecurityAutoConfiguration {
|
||||||
return matcher;
|
return matcher;
|
||||||
}
|
}
|
||||||
// Match everything, including the sensitive and non-sensitive paths
|
// Match everything, including the sensitive and non-sensitive paths
|
||||||
return new LazyEndpointPathRequestMatcher(contextResolver, EndpointPaths.ALL);
|
return new LazyEndpointPathRequestMatcher(contextResolver,
|
||||||
|
new EndpointPaths());
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyEndpointPathRequestMatcher(ManagementContextResolver contextResolver,
|
LazyEndpointPathRequestMatcher(ManagementContextResolver contextResolver,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ class CloudFoundryDiscoveryMvcEndpoint extends AbstractMvcEndpoint {
|
||||||
private final Set<NamedMvcEndpoint> endpoints;
|
private final Set<NamedMvcEndpoint> endpoints;
|
||||||
|
|
||||||
CloudFoundryDiscoveryMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
CloudFoundryDiscoveryMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
||||||
super("", false);
|
super("");
|
||||||
this.endpoints = endpoints;
|
this.endpoints = endpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,47 +41,27 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||||
*/
|
*/
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private final boolean sensitiveDefault;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark if the endpoint exposes sensitive information.
|
|
||||||
*/
|
|
||||||
private Boolean sensitive;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable the endpoint.
|
* Enable the endpoint.
|
||||||
*/
|
*/
|
||||||
private Boolean enabled;
|
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
|
* Create a new endpoint instance. The endpoint will enabled flag will be based on the
|
||||||
* spring {@link Environment} unless explicitly set.
|
* spring {@link Environment} unless explicitly set.
|
||||||
* @param id the endpoint ID
|
* @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);
|
setId(id);
|
||||||
this.sensitiveDefault = sensitive;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new endpoint instance.
|
* Create a new endpoint instance.
|
||||||
* @param id the endpoint ID
|
* @param id the endpoint ID
|
||||||
* @param sensitive if the endpoint is sensitive
|
|
||||||
* @param enabled if the endpoint is enabled or not.
|
* @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);
|
setId(id);
|
||||||
this.sensitiveDefault = sensitive;
|
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,14 +95,4 @@ public abstract class AbstractEndpoint<T> implements Endpoint<T>, EnvironmentAwa
|
||||||
this.enabled = enabled;
|
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();
|
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.
|
* Called to invoke the endpoint.
|
||||||
* @return the results of the invocation
|
* @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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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_ENABLED_PROPERTY = "endpoints.enabled";
|
||||||
|
|
||||||
private static final String ENDPOINTS_SENSITIVE_PROPERTY = "endpoints.sensitive";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable endpoints.
|
* Enable endpoints.
|
||||||
*/
|
*/
|
||||||
private Boolean enabled = true;
|
private Boolean enabled = true;
|
||||||
|
|
||||||
/**
|
|
||||||
* Default endpoint sensitive setting.
|
|
||||||
*/
|
|
||||||
private Boolean sensitive;
|
|
||||||
|
|
||||||
public Boolean getEnabled() {
|
public Boolean getEnabled() {
|
||||||
return this.enabled;
|
return this.enabled;
|
||||||
}
|
}
|
||||||
|
|
@ -50,14 +43,6 @@ public class EndpointProperties {
|
||||||
this.enabled = 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
|
* Determine if an endpoint is enabled based on its specific property and taking into
|
||||||
* account the global default.
|
* account the global default.
|
||||||
|
|
@ -76,25 +61,4 @@ public class EndpointProperties {
|
||||||
return true;
|
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,
|
public HealthEndpoint(HealthAggregator healthAggregator,
|
||||||
Map<String, HealthIndicator> healthIndicators) {
|
Map<String, HealthIndicator> healthIndicators) {
|
||||||
super("health", false);
|
super("health");
|
||||||
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
Assert.notNull(healthAggregator, "HealthAggregator must not be null");
|
||||||
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
Assert.notNull(healthIndicators, "HealthIndicators must not be null");
|
||||||
CompositeHealthIndicator healthIndicator = new CompositeHealthIndicator(
|
CompositeHealthIndicator healthIndicator = new CompositeHealthIndicator(
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public class InfoEndpoint extends AbstractEndpoint<Map<String, Object>> {
|
||||||
* @param infoContributors the info contributors to use
|
* @param infoContributors the info contributors to use
|
||||||
*/
|
*/
|
||||||
public InfoEndpoint(List<InfoContributor> infoContributors) {
|
public InfoEndpoint(List<InfoContributor> infoContributors) {
|
||||||
super("info", false);
|
super("info");
|
||||||
Assert.notNull(infoContributors, "Info contributors must not be null");
|
Assert.notNull(infoContributors, "Info contributors must not be null");
|
||||||
this.infoContributors = infoContributors;
|
this.infoContributors = infoContributors;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public class ShutdownEndpoint extends AbstractEndpoint<Map<String, Object>>
|
||||||
* Create a new {@link ShutdownEndpoint} instance.
|
* Create a new {@link ShutdownEndpoint} instance.
|
||||||
*/
|
*/
|
||||||
public ShutdownEndpoint() {
|
public ShutdownEndpoint() {
|
||||||
super("shutdown", true, false);
|
super("shutdown", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -64,11 +64,6 @@ public abstract class EndpointMBean implements JmxEndpoint {
|
||||||
return this.endpoint.isEnabled();
|
return this.endpoint.isEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManagedAttribute(description = "Indicates whether the underlying endpoint exposes sensitive information")
|
|
||||||
public boolean isSensitive() {
|
|
||||||
return this.endpoint.isSensitive();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIdentity() {
|
public String getIdentity() {
|
||||||
return ObjectUtils.getIdentityHexString(getEndpoint());
|
return ObjectUtils.getIdentityHexString(getEndpoint());
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,6 @@ public abstract class AbstractEndpointMvcAdapter<E extends Endpoint<?>>
|
||||||
this.path = path;
|
this.path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSensitive() {
|
|
||||||
return this.delegate.isSensitive();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public Class<? extends Endpoint> getEndpointType() {
|
public Class<? extends Endpoint> getEndpointType() {
|
||||||
|
|
|
||||||
|
|
@ -46,22 +46,8 @@ public abstract class AbstractMvcEndpoint
|
||||||
*/
|
*/
|
||||||
private Boolean enabled;
|
private Boolean enabled;
|
||||||
|
|
||||||
/**
|
public AbstractMvcEndpoint(String path) {
|
||||||
* Mark if the endpoint exposes sensitive information.
|
|
||||||
*/
|
|
||||||
private Boolean sensitive;
|
|
||||||
|
|
||||||
private final boolean sensitiveDefault;
|
|
||||||
|
|
||||||
public AbstractMvcEndpoint(String path, boolean sensitive) {
|
|
||||||
setPath(path);
|
setPath(path);
|
||||||
this.sensitiveDefault = sensitive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractMvcEndpoint(String path, boolean sensitive, boolean enabled) {
|
|
||||||
setPath(path);
|
|
||||||
this.sensitiveDefault = sensitive;
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -93,16 +79,6 @@ public abstract class AbstractMvcEndpoint
|
||||||
this.enabled = enabled;
|
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
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public Class<? extends Endpoint> getEndpointType() {
|
public Class<? extends Endpoint> getEndpointType() {
|
||||||
|
|
|
||||||
|
|
@ -31,15 +31,8 @@ public abstract class AbstractNamedMvcEndpoint extends AbstractMvcEndpoint
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public AbstractNamedMvcEndpoint(String name, String path, boolean sensitive) {
|
public AbstractNamedMvcEndpoint(String name, String path) {
|
||||||
super(path, sensitive);
|
super(path);
|
||||||
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);
|
|
||||||
Assert.hasLength(name, "Name must not be empty");
|
Assert.hasLength(name, "Name must not be empty");
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public class AuditEventsMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||||
private final AuditEventRepository auditEventRepository;
|
private final AuditEventRepository auditEventRepository;
|
||||||
|
|
||||||
public AuditEventsMvcEndpoint(AuditEventRepository auditEventRepository) {
|
public AuditEventsMvcEndpoint(AuditEventRepository auditEventRepository) {
|
||||||
super("auditevents", "/auditevents", true);
|
super("auditevents", "/auditevents");
|
||||||
Assert.notNull(auditEventRepository, "AuditEventRepository must not be null");
|
Assert.notNull(auditEventRepository, "AuditEventRepository must not be null");
|
||||||
this.auditEventRepository = auditEventRepository;
|
this.auditEventRepository = auditEventRepository;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ public class EndpointHandlerMapping extends AbstractEndpointHandlerMapping<MvcEn
|
||||||
private final Set<NamedMvcEndpoint> endpoints;
|
private final Set<NamedMvcEndpoint> endpoints;
|
||||||
|
|
||||||
private EndpointLinksMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
private EndpointLinksMvcEndpoint(Set<NamedMvcEndpoint> endpoints) {
|
||||||
super("", false);
|
super("");
|
||||||
this.endpoints = endpoints;
|
this.endpoints = endpoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public class HeapdumpMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HeapdumpMvcEndpoint(long timeout) {
|
protected HeapdumpMvcEndpoint(long timeout) {
|
||||||
super("heapdump", "/heapdump", true);
|
super("heapdump", "/heapdump");
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ public class JolokiaMvcEndpoint extends AbstractNamedMvcEndpoint implements
|
||||||
private final ServletWrappingController controller = new ServletWrappingController();
|
private final ServletWrappingController controller = new ServletWrappingController();
|
||||||
|
|
||||||
public JolokiaMvcEndpoint() {
|
public JolokiaMvcEndpoint() {
|
||||||
super("jolokia", "/jolokia", true);
|
super("jolokia", "/jolokia");
|
||||||
this.controller.setServletClass(AgentServlet.class);
|
this.controller.setServletClass(AgentServlet.class);
|
||||||
this.controller.setServletName("jolokia");
|
this.controller.setServletName("jolokia");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ public class LogFileMvcEndpoint extends AbstractNamedMvcEndpoint {
|
||||||
private File externalFile;
|
private File externalFile;
|
||||||
|
|
||||||
public LogFileMvcEndpoint() {
|
public LogFileMvcEndpoint() {
|
||||||
super("logfile", "/logfile", true);
|
super("logfile", "/logfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getExternalFile() {
|
public File getExternalFile() {
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,6 @@ public interface MvcEndpoint {
|
||||||
*/
|
*/
|
||||||
String getPath();
|
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
|
* Return the type of {@link Endpoint} exposed, or {@code null} if this
|
||||||
* {@link MvcEndpoint} exposes information that cannot be represented as a traditional
|
* {@link MvcEndpoint} exposes information that cannot be represented as a traditional
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,6 @@ public class MvcEndpointSecurityInterceptor extends HandlerInterceptorAdapter {
|
||||||
&& !(handlerMethod.getBean() instanceof MvcEndpoint)) {
|
&& !(handlerMethod.getBean() instanceof MvcEndpoint)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MvcEndpoint mvcEndpoint = (MvcEndpoint) handlerMethod.getBean();
|
|
||||||
if (!mvcEndpoint.isSensitive()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (isUserAllowedAccess(request)) {
|
if (isUserAllowedAccess(request)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
||||||
public static class ManagedEndpoint extends AbstractEndpoint<Boolean> {
|
public static class ManagedEndpoint extends AbstractEndpoint<Boolean> {
|
||||||
|
|
||||||
public ManagedEndpoint() {
|
public ManagedEndpoint() {
|
||||||
super("managed", true);
|
super("managed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -200,7 +200,7 @@ public class EndpointMBeanExportAutoConfigurationTests {
|
||||||
class Nested extends AbstractEndpoint<Boolean> {
|
class Nested extends AbstractEndpoint<Boolean> {
|
||||||
|
|
||||||
Nested() {
|
Nested() {
|
||||||
super("managed", true);
|
super("managed");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -867,11 +867,6 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||||
return "/endpoint";
|
return "/endpoint";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSensitive() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public Class<? extends Endpoint> getEndpointType() {
|
public Class<? extends Endpoint> getEndpointType() {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ public class LinksEnhancerTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void usePathAsRelIfNameNotAvailable() throws Exception {
|
public void usePathAsRelIfNameNotAvailable() throws Exception {
|
||||||
MvcEndpoint endpoint = new NoNameTestMvcEndpoint("/a", false);
|
MvcEndpoint endpoint = new NoNameTestMvcEndpoint("/a");
|
||||||
LinksEnhancer enhancer = getLinksEnhancer(Collections.singletonList(endpoint));
|
LinksEnhancer enhancer = getLinksEnhancer(Collections.singletonList(endpoint));
|
||||||
ResourceSupport support = new ResourceSupport();
|
ResourceSupport support = new ResourceSupport();
|
||||||
enhancer.addEndpointLinks(support, "");
|
enhancer.addEndpointLinks(support, "");
|
||||||
|
|
@ -143,8 +143,8 @@ public class LinksEnhancerTests {
|
||||||
|
|
||||||
private static class NoNameTestMvcEndpoint extends AbstractMvcEndpoint {
|
private static class NoNameTestMvcEndpoint extends AbstractMvcEndpoint {
|
||||||
|
|
||||||
NoNameTestMvcEndpoint(String path, boolean sensitive) {
|
NoNameTestMvcEndpoint(String path) {
|
||||||
super(path, sensitive);
|
super(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,6 @@ import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
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}.
|
* Tests for {@link ManagementWebSecurityAutoConfiguration}.
|
||||||
|
|
@ -226,27 +223,6 @@ public class ManagementWebSecurityAutoConfigurationTests {
|
||||||
.andExpect(springAuthenticateRealmHeader());
|
.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() {
|
private ResultMatcher springAuthenticateRealmHeader() {
|
||||||
return MockMvcResultMatchers.header().string("www-authenticate",
|
return MockMvcResultMatchers.header().string("www-authenticate",
|
||||||
Matchers.containsString("realm=\"Spring\""));
|
Matchers.containsString("realm=\"Spring\""));
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ public class CloudFoundryHealthMvcEndpointTests {
|
||||||
CloudFoundryHealthMvcEndpoint mvc = new CloudFoundryHealthMvcEndpoint(endpoint);
|
CloudFoundryHealthMvcEndpoint mvc = new CloudFoundryHealthMvcEndpoint(endpoint);
|
||||||
given(endpoint.invoke())
|
given(endpoint.invoke())
|
||||||
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
|
.willReturn(new Health.Builder().up().withDetail("foo", "bar").build());
|
||||||
given(endpoint.isSensitive()).willReturn(false);
|
|
||||||
Object result = mvc.invoke(null, null);
|
Object result = mvc.invoke(null, null);
|
||||||
assertThat(result instanceof Health).isTrue();
|
assertThat(result instanceof Health).isTrue();
|
||||||
assertThat(((Health) result).getStatus() == Status.UP).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 String id;
|
||||||
|
|
||||||
private final boolean sensitive;
|
|
||||||
|
|
||||||
private final String property;
|
private final String property;
|
||||||
|
|
||||||
public AbstractEndpointTests(Class<?> configClass, Class<?> type, String id,
|
public AbstractEndpointTests(Class<?> configClass, Class<?> type, String id,
|
||||||
boolean sensitive, String property) {
|
String property) {
|
||||||
this.configClass = configClass;
|
this.configClass = configClass;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.sensitive = sensitive;
|
|
||||||
this.property = property;
|
this.property = property;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,11 +78,6 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||||
assertThat(getEndpointBean().getId()).isEqualTo(this.id);
|
assertThat(getEndpointBean().getId()).isEqualTo(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isSensitive() throws Exception {
|
|
||||||
assertThat(getEndpointBean().isSensitive()).isEqualTo(this.sensitive);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void idOverride() throws Exception {
|
public void idOverride() throws Exception {
|
||||||
this.context = new AnnotationConfigApplicationContext();
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
|
|
@ -95,31 +87,6 @@ public abstract class AbstractEndpointTests<T extends Endpoint<?>> {
|
||||||
assertThat(getEndpointBean().getId()).isEqualTo("myid");
|
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
|
@Test
|
||||||
public void isEnabledByDefault() throws Exception {
|
public void isEnabledByDefault() throws Exception {
|
||||||
assertThat(getEndpointBean().isEnabled()).isTrue();
|
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")
|
@SuppressWarnings("unchecked")
|
||||||
protected T getEndpointBean() {
|
protected T getEndpointBean() {
|
||||||
return (T) this.context.getBean(this.type);
|
return (T) this.context.getBean(this.type);
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ public class AutoConfigurationReportEndpointTests
|
||||||
extends AbstractEndpointTests<AutoConfigurationReportEndpoint> {
|
extends AbstractEndpointTests<AutoConfigurationReportEndpoint> {
|
||||||
|
|
||||||
public AutoConfigurationReportEndpointTests() {
|
public AutoConfigurationReportEndpointTests() {
|
||||||
super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig", true,
|
super(Config.class, AutoConfigurationReportEndpoint.class, "autoconfig",
|
||||||
"endpoints.autoconfig");
|
"endpoints.autoconfig");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class BeansEndpointTests extends AbstractEndpointTests<BeansEndpoint> {
|
public class BeansEndpointTests extends AbstractEndpointTests<BeansEndpoint> {
|
||||||
|
|
||||||
public BeansEndpointTests() {
|
public BeansEndpointTests() {
|
||||||
super(Config.class, BeansEndpoint.class, "beans", true, "endpoints.beans");
|
super(Config.class, BeansEndpoint.class, "beans", "endpoints.beans");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public class ConfigurationPropertiesReportEndpointTests
|
||||||
|
|
||||||
public ConfigurationPropertiesReportEndpointTests() {
|
public ConfigurationPropertiesReportEndpointTests() {
|
||||||
super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops",
|
super(Config.class, ConfigurationPropertiesReportEndpoint.class, "configprops",
|
||||||
true, "endpoints.configprops");
|
"endpoints.configprops");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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 class DumpEndpointTests extends AbstractEndpointTests<DumpEndpoint> {
|
||||||
|
|
||||||
public DumpEndpointTests() {
|
public DumpEndpointTests() {
|
||||||
super(Config.class, DumpEndpoint.class, "dump", true, "endpoints.dump");
|
super(Config.class, DumpEndpoint.class, "dump", "endpoints.dump");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentEndpoint> {
|
public class EnvironmentEndpointTests extends AbstractEndpointTests<EnvironmentEndpoint> {
|
||||||
|
|
||||||
public EnvironmentEndpointTests() {
|
public EnvironmentEndpointTests() {
|
||||||
super(Config.class, EnvironmentEndpoint.class, "env", true, "endpoints.env");
|
super(Config.class, EnvironmentEndpoint.class, "env", "endpoints.env");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class FlywayEndpointTests extends AbstractEndpointTests<FlywayEndpoint> {
|
public class FlywayEndpointTests extends AbstractEndpointTests<FlywayEndpoint> {
|
||||||
|
|
||||||
public FlywayEndpointTests() {
|
public FlywayEndpointTests() {
|
||||||
super(Config.class, FlywayEndpoint.class, "flyway", true, "endpoints.flyway");
|
super(Config.class, FlywayEndpoint.class, "flyway", "endpoints.flyway");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
|
public class HealthEndpointTests extends AbstractEndpointTests<HealthEndpoint> {
|
||||||
|
|
||||||
public HealthEndpointTests() {
|
public HealthEndpointTests() {
|
||||||
super(Config.class, HealthEndpoint.class, "health", false, "endpoints.health");
|
super(Config.class, HealthEndpoint.class, "health", "endpoints.health");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class InfoEndpointTests extends AbstractEndpointTests<InfoEndpoint> {
|
public class InfoEndpointTests extends AbstractEndpointTests<InfoEndpoint> {
|
||||||
|
|
||||||
public InfoEndpointTests() {
|
public InfoEndpointTests() {
|
||||||
super(Config.class, InfoEndpoint.class, "info", false, "endpoints.info");
|
super(Config.class, InfoEndpoint.class, "info", "endpoints.info");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class LiquibaseEndpointTests extends AbstractEndpointTests<LiquibaseEndpoint> {
|
public class LiquibaseEndpointTests extends AbstractEndpointTests<LiquibaseEndpoint> {
|
||||||
|
|
||||||
public LiquibaseEndpointTests() {
|
public LiquibaseEndpointTests() {
|
||||||
super(Config.class, LiquibaseEndpoint.class, "liquibase", true,
|
super(Config.class, LiquibaseEndpoint.class, "liquibase", "endpoints.liquibase");
|
||||||
"endpoints.liquibase");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ import static org.mockito.Mockito.verify;
|
||||||
public class LoggersEndpointTests extends AbstractEndpointTests<LoggersEndpoint> {
|
public class LoggersEndpointTests extends AbstractEndpointTests<LoggersEndpoint> {
|
||||||
|
|
||||||
public LoggersEndpointTests() {
|
public LoggersEndpointTests() {
|
||||||
super(Config.class, LoggersEndpoint.class, "loggers", true, "endpoints.loggers");
|
super(Config.class, LoggersEndpoint.class, "loggers", "endpoints.loggers");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public class MetricsEndpointTests extends AbstractEndpointTests<MetricsEndpoint>
|
||||||
private Metric<Number> metric3 = new Metric<>("c", 3);
|
private Metric<Number> metric3 = new Metric<>("c", 3);
|
||||||
|
|
||||||
public MetricsEndpointTests() {
|
public MetricsEndpointTests() {
|
||||||
super(Config.class, MetricsEndpoint.class, "metrics", true, "endpoints.metrics");
|
super(Config.class, MetricsEndpoint.class, "metrics", "endpoints.metrics");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class ShutdownEndpointTests extends AbstractEndpointTests<ShutdownEndpoint> {
|
public class ShutdownEndpointTests extends AbstractEndpointTests<ShutdownEndpoint> {
|
||||||
|
|
||||||
public ShutdownEndpointTests() {
|
public ShutdownEndpointTests() {
|
||||||
super(Config.class, ShutdownEndpoint.class, "shutdown", true,
|
super(Config.class, ShutdownEndpoint.class, "shutdown", "endpoints.shutdown");
|
||||||
"endpoints.shutdown");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
public class TraceEndpointTests extends AbstractEndpointTests<TraceEndpoint> {
|
public class TraceEndpointTests extends AbstractEndpointTests<TraceEndpoint> {
|
||||||
|
|
||||||
public TraceEndpointTests() {
|
public TraceEndpointTests() {
|
||||||
super(Config.class, TraceEndpoint.class, "trace", true, "endpoints.trace");
|
super(Config.class, TraceEndpoint.class, "trace", "endpoints.trace");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,8 @@ public class EndpointMBeanExporterTests {
|
||||||
MBeanInfo mbeanInfo = mbeanExporter.getServer()
|
MBeanInfo mbeanInfo = mbeanExporter.getServer()
|
||||||
.getMBeanInfo(getObjectName("endpoint1", this.context));
|
.getMBeanInfo(getObjectName("endpoint1", this.context));
|
||||||
assertThat(mbeanInfo).isNotNull();
|
assertThat(mbeanInfo).isNotNull();
|
||||||
assertThat(mbeanInfo.getOperations().length).isEqualTo(3);
|
assertThat(mbeanInfo.getOperations().length).isEqualTo(2);
|
||||||
assertThat(mbeanInfo.getAttributes().length).isEqualTo(3);
|
assertThat(mbeanInfo.getAttributes().length).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
@TestPropertySource(properties = { "info.app.name=MyService" })
|
@TestPropertySource(properties = { "info.app.name=MyService",
|
||||||
|
"management.security.enabled=false" })
|
||||||
public class InfoMvcEndpointTests {
|
public class InfoMvcEndpointTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
@ -50,6 +51,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||||
*/
|
*/
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
|
@TestPropertySource(properties = "management.security.enabled=false")
|
||||||
public class InfoMvcEndpointWithNoInfoContributorsTests {
|
public class InfoMvcEndpointWithNoInfoContributorsTests {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
||||||
|
|
@ -112,28 +112,7 @@ public class MvcEndpointIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void nonSensitiveEndpointsAreNotSecureByDefault() throws Exception {
|
public void endpointsAreSecureByDefault() 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 {
|
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.register(SecureConfiguration.class);
|
this.context.register(SecureConfiguration.class);
|
||||||
MockMvc mockMvc = createSecureMockMvc();
|
MockMvc mockMvc = createSecureMockMvc();
|
||||||
|
|
@ -141,8 +120,7 @@ public class MvcEndpointIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointsAreSecureByDefaultWithCustomContextPath()
|
public void endpointsAreSecureByDefaultWithCustomContextPath() throws Exception {
|
||||||
throws Exception {
|
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
this.context.register(SecureConfiguration.class);
|
this.context.register(SecureConfiguration.class);
|
||||||
TestPropertyValues.of("management.context-path:/management")
|
TestPropertyValues.of("management.context-path:/management")
|
||||||
|
|
@ -152,7 +130,7 @@ public class MvcEndpointIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointsAreSecureWithNonActuatorRoleWithCustomContextPath()
|
public void endpointsAreSecureWithNonActuatorRoleWithCustomContextPath()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
TestSecurityContextHolder.getContext().setAuthentication(
|
TestSecurityContextHolder.getContext().setAuthentication(
|
||||||
new TestingAuthenticationToken("user", "N/A", "ROLE_USER"));
|
new TestingAuthenticationToken("user", "N/A", "ROLE_USER"));
|
||||||
|
|
@ -165,7 +143,7 @@ public class MvcEndpointIntegrationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointsAreSecureWithActuatorRoleWithCustomContextPath()
|
public void endpointsAreSecureWithActuatorRoleWithCustomContextPath()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
TestSecurityContextHolder.getContext().setAuthentication(
|
TestSecurityContextHolder.getContext().setAuthentication(
|
||||||
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
|
||||||
|
|
|
||||||
|
|
@ -89,22 +89,14 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void endpointNotSensitiveShouldAllowAccess() throws Exception {
|
public void endpointIfRoleIsPresentShouldAllowAccess() throws Exception {
|
||||||
this.endpoint.setSensitive(false);
|
|
||||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
|
||||||
this.handlerMethod)).isTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void sensitiveEndpointIfRoleIsPresentShouldAllowAccess() throws Exception {
|
|
||||||
this.servletContext.declareRoles("SUPER_HERO");
|
this.servletContext.declareRoles("SUPER_HERO");
|
||||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||||
this.handlerMethod)).isTrue();
|
this.handlerMethod)).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfNotAuthenticatedShouldNotAllowAccess()
|
public void endpointIfNotAuthenticatedShouldNotAllowAccess() throws Exception {
|
||||||
throws Exception {
|
|
||||||
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
assertThat(this.securityInterceptor.preHandle(this.request, this.response,
|
||||||
this.handlerMethod)).isFalse();
|
this.handlerMethod)).isFalse();
|
||||||
verify(this.response).sendError(HttpStatus.UNAUTHORIZED.value(),
|
verify(this.response).sendError(HttpStatus.UNAUTHORIZED.value(),
|
||||||
|
|
@ -118,8 +110,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfRoleIsNotCorrectShouldNotAllowAccess()
|
public void endpointIfRoleIsNotCorrectShouldNotAllowAccess() throws Exception {
|
||||||
throws Exception {
|
|
||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
this.request.setUserPrincipal(principal);
|
this.request.setUserPrincipal(principal);
|
||||||
this.servletContext.declareRoles("HERO");
|
this.servletContext.declareRoles("HERO");
|
||||||
|
|
@ -130,8 +121,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfRoleNotCorrectShouldCheckAuthorities()
|
public void endpointIfRoleNotCorrectShouldCheckAuthorities() throws Exception {
|
||||||
throws Exception {
|
|
||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
this.request.setUserPrincipal(principal);
|
this.request.setUserPrincipal(principal);
|
||||||
Authentication authentication = mock(Authentication.class);
|
Authentication authentication = mock(Authentication.class);
|
||||||
|
|
@ -144,7 +134,7 @@ public class MvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess()
|
public void endpointIfRoleAndAuthoritiesNotCorrectShouldNotAllowAccess()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
this.request.setUserPrincipal(principal);
|
this.request.setUserPrincipal(principal);
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.boot.actuate.endpoint.mvc;
|
package org.springframework.boot.actuate.endpoint.mvc;
|
||||||
|
|
||||||
import java.security.Principal;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
@ -38,12 +36,10 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
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.test.web.servlet.setup.MockMvcBuilders;
|
||||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
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.request.MockMvcRequestBuilders.get;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
@ -65,19 +61,6 @@ public class NoSpringSecurityHealthMvcEndpointIntegrationTests {
|
||||||
this.context.close();
|
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
|
@Test
|
||||||
public void healthDetailPresent() throws Exception {
|
public void healthDetailPresent() throws Exception {
|
||||||
this.context = new AnnotationConfigWebApplicationContext();
|
this.context = new AnnotationConfigWebApplicationContext();
|
||||||
|
|
@ -91,14 +74,6 @@ public class NoSpringSecurityHealthMvcEndpointIntegrationTests {
|
||||||
"\"status\":\"UP\",\"test\":{\"status\":\"UP\",\"hello\":\"world\"}")));
|
"\"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,
|
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
|
||||||
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
|
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||||
EndpointWebMvcAutoConfiguration.class,
|
EndpointWebMvcAutoConfiguration.class,
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,7 @@ public class NoSpringSecurityMvcEndpointSecurityInterceptorTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointIfRoleNotPresentShouldNotValidateAuthorities()
|
public void endpointIfRoleNotPresentShouldNotValidateAuthorities() throws Exception {
|
||||||
throws Exception {
|
|
||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
this.request.setUserPrincipal(principal);
|
this.request.setUserPrincipal(principal);
|
||||||
this.servletContext.declareRoles("HERO");
|
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 ({sc-spring-boot-actuator}/endpoint/AbstractEndpoint.{sc-ext}[AbstractEndpoint] subclasses)
|
||||||
endpoints.enabled=true # Enable endpoints.
|
endpoints.enabled=true # Enable endpoints.
|
||||||
endpoints.sensitive= # Default endpoint sensitive setting.
|
|
||||||
endpoints.auditevents.enabled= # Enable the endpoint.
|
endpoints.auditevents.enabled= # Enable the endpoint.
|
||||||
endpoints.auditevents.path= # Endpoint path.
|
endpoints.auditevents.path= # Endpoint path.
|
||||||
endpoints.auditevents.sensitive=false # Enable security on the endpoint.
|
|
||||||
endpoints.autoconfig.enabled= # Enable the endpoint.
|
endpoints.autoconfig.enabled= # Enable the endpoint.
|
||||||
endpoints.autoconfig.id= # Endpoint identifier.
|
endpoints.autoconfig.id= # Endpoint identifier.
|
||||||
endpoints.autoconfig.path= # Endpoint path.
|
endpoints.autoconfig.path= # Endpoint path.
|
||||||
endpoints.autoconfig.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.beans.enabled= # Enable the endpoint.
|
endpoints.beans.enabled= # Enable the endpoint.
|
||||||
endpoints.beans.id= # Endpoint identifier.
|
endpoints.beans.id= # Endpoint identifier.
|
||||||
endpoints.beans.path= # Endpoint path.
|
endpoints.beans.path= # Endpoint path.
|
||||||
endpoints.beans.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.configprops.enabled= # Enable the endpoint.
|
endpoints.configprops.enabled= # Enable the endpoint.
|
||||||
endpoints.configprops.id= # Endpoint identifier.
|
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.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.path= # Endpoint path.
|
||||||
endpoints.configprops.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.docs.curies.enabled=false # Enable the curie generation.
|
endpoints.docs.curies.enabled=false # Enable the curie generation.
|
||||||
endpoints.docs.enabled=true # Enable actuator docs endpoint.
|
endpoints.docs.enabled=true # Enable actuator docs endpoint.
|
||||||
endpoints.docs.path=/docs #
|
endpoints.docs.path=/docs #
|
||||||
endpoints.docs.sensitive=false #
|
|
||||||
endpoints.dump.enabled= # Enable the endpoint.
|
endpoints.dump.enabled= # Enable the endpoint.
|
||||||
endpoints.dump.id= # Endpoint identifier.
|
endpoints.dump.id= # Endpoint identifier.
|
||||||
endpoints.dump.path= # Endpoint path.
|
endpoints.dump.path= # Endpoint path.
|
||||||
endpoints.dump.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.env.enabled= # Enable the endpoint.
|
endpoints.env.enabled= # Enable the endpoint.
|
||||||
endpoints.env.id= # Endpoint identifier.
|
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.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.path= # Endpoint path.
|
||||||
endpoints.env.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.flyway.enabled= # Enable the endpoint.
|
endpoints.flyway.enabled= # Enable the endpoint.
|
||||||
endpoints.flyway.id= # Endpoint identifier.
|
endpoints.flyway.id= # Endpoint identifier.
|
||||||
endpoints.flyway.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.health.enabled= # Enable the endpoint.
|
endpoints.health.enabled= # Enable the endpoint.
|
||||||
endpoints.health.id= # Endpoint identifier.
|
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.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.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.health.time-to-live=1000 # Time to live for cached result, in milliseconds.
|
||||||
endpoints.heapdump.enabled= # Enable the endpoint.
|
endpoints.heapdump.enabled= # Enable the endpoint.
|
||||||
endpoints.heapdump.path= # Endpoint path.
|
endpoints.heapdump.path= # Endpoint path.
|
||||||
endpoints.heapdump.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.info.enabled= # Enable the endpoint.
|
endpoints.info.enabled= # Enable the endpoint.
|
||||||
endpoints.info.id= # Endpoint identifier.
|
endpoints.info.id= # Endpoint identifier.
|
||||||
endpoints.info.path= # Endpoint path.
|
endpoints.info.path= # Endpoint path.
|
||||||
endpoints.info.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.jolokia.enabled=true # Enable Jolokia endpoint.
|
endpoints.jolokia.enabled=true # Enable Jolokia endpoint.
|
||||||
endpoints.jolokia.path=/jolokia # Endpoint URL path.
|
endpoints.jolokia.path=/jolokia # Endpoint URL path.
|
||||||
endpoints.jolokia.sensitive=true # Enable security on the endpoint.
|
|
||||||
endpoints.liquibase.enabled= # Enable the endpoint.
|
endpoints.liquibase.enabled= # Enable the endpoint.
|
||||||
endpoints.liquibase.id= # Endpoint identifier.
|
endpoints.liquibase.id= # Endpoint identifier.
|
||||||
endpoints.liquibase.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.logfile.enabled=true # Enable the endpoint.
|
endpoints.logfile.enabled=true # Enable the endpoint.
|
||||||
endpoints.logfile.external-file= # External Logfile to be accessed.
|
endpoints.logfile.external-file= # External Logfile to be accessed.
|
||||||
endpoints.logfile.path=/logfile # Endpoint URL path.
|
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.enabled=true # Enable the endpoint.
|
||||||
endpoints.loggers.id= # Endpoint identifier.
|
endpoints.loggers.id= # Endpoint identifier.
|
||||||
endpoints.loggers.path=/logfile # Endpoint path.
|
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.enabled= # Enable the endpoint.
|
||||||
endpoints.mappings.id= # Endpoint identifier.
|
endpoints.mappings.id= # Endpoint identifier.
|
||||||
endpoints.mappings.path= # Endpoint path.
|
endpoints.mappings.path= # Endpoint path.
|
||||||
endpoints.mappings.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.metrics.enabled= # Enable the endpoint.
|
endpoints.metrics.enabled= # Enable the endpoint.
|
||||||
endpoints.metrics.filter.enabled=true # Enable the metrics servlet filter.
|
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.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.filter.counter-submissions=merged # Http filter counter submissions (merged, per-http-method)
|
||||||
endpoints.metrics.id= # Endpoint identifier.
|
endpoints.metrics.id= # Endpoint identifier.
|
||||||
endpoints.metrics.path= # Endpoint path.
|
endpoints.metrics.path= # Endpoint path.
|
||||||
endpoints.metrics.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.shutdown.enabled= # Enable the endpoint.
|
endpoints.shutdown.enabled= # Enable the endpoint.
|
||||||
endpoints.shutdown.id= # Endpoint identifier.
|
endpoints.shutdown.id= # Endpoint identifier.
|
||||||
endpoints.shutdown.path= # Endpoint path.
|
endpoints.shutdown.path= # Endpoint path.
|
||||||
endpoints.shutdown.sensitive= # Mark if the endpoint exposes sensitive information.
|
|
||||||
endpoints.trace.enabled= # Enable the endpoint.
|
endpoints.trace.enabled= # Enable the endpoint.
|
||||||
endpoints.trace.filter.enabled=true # Enable the trace servlet filter.
|
endpoints.trace.filter.enabled=true # Enable the trace servlet filter.
|
||||||
endpoints.trace.id= # Endpoint identifier.
|
endpoints.trace.id= # Endpoint identifier.
|
||||||
endpoints.trace.path= # Endpoint path.
|
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 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.
|
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"]
|
[cols="2,5,1"]
|
||||||
|===
|
|===
|
||||||
| ID | Description | Sensitive Default
|
| ID | Description
|
||||||
|
|
||||||
|`auditevents`
|
|`auditevents`
|
||||||
|Exposes audit events information for the current application.
|
|Exposes audit events information for the current application.
|
||||||
|true
|
|
||||||
|
|
||||||
|`autoconfig`
|
|`autoconfig`
|
||||||
|Displays an auto-configuration report showing all auto-configuration candidates and the
|
|Displays an auto-configuration report showing all auto-configuration candidates and the
|
||||||
reason why they '`were`' or '`were not`' applied.
|
reason why they '`were`' or '`were not`' applied.
|
||||||
|true
|
|
||||||
|
|
||||||
|`beans`
|
|`beans`
|
||||||
|Displays a complete list of all the Spring beans in your application.
|
|Displays a complete list of all the Spring beans in your application.
|
||||||
|true
|
|
||||||
|
|
||||||
|`configprops`
|
|`configprops`
|
||||||
|Displays a collated list of all `@ConfigurationProperties`.
|
|Displays a collated list of all `@ConfigurationProperties`.
|
||||||
|true
|
|
||||||
|
|
||||||
|`dump`
|
|`dump`
|
||||||
|Performs a thread dump.
|
|Performs a thread dump.
|
||||||
|true
|
|
||||||
|
|
||||||
|`env`
|
|`env`
|
||||||
|Exposes properties from Spring's `ConfigurableEnvironment`.
|
|Exposes properties from Spring's `ConfigurableEnvironment`.
|
||||||
|true
|
|
||||||
|
|
||||||
|`flyway`
|
|`flyway`
|
||||||
|Shows any Flyway database migrations that have been applied.
|
|Shows any Flyway database migrations that have been applied.
|
||||||
|true
|
|
||||||
|
|
||||||
|`health`
|
|`health`
|
||||||
|Shows application health information (when the application is secure, a simple '`status`'
|
|Shows application health information.
|
||||||
when accessed over an unauthenticated connection or full message details when
|
|
||||||
authenticated).
|
|
||||||
|false
|
|
||||||
|
|
||||||
|`info`
|
|`info`
|
||||||
|Displays arbitrary application info.
|
|Displays arbitrary application info.
|
||||||
|false
|
|
||||||
|
|
||||||
|`loggers`
|
|`loggers`
|
||||||
|Shows and modifies the configuration of loggers in the application.
|
|Shows and modifies the configuration of loggers in the application.
|
||||||
|true
|
|
||||||
|
|
||||||
|`liquibase`
|
|`liquibase`
|
||||||
|Shows any Liquibase database migrations that have been applied.
|
|Shows any Liquibase database migrations that have been applied.
|
||||||
|true
|
|
||||||
|
|
||||||
|`metrics`
|
|`metrics`
|
||||||
|Shows '`metrics`' information for the current application.
|
|Shows '`metrics`' information for the current application.
|
||||||
|true
|
|
||||||
|
|
||||||
|`mappings`
|
|`mappings`
|
||||||
|Displays a collated list of all `@RequestMapping` paths.
|
|Displays a collated list of all `@RequestMapping` paths.
|
||||||
|true
|
|
||||||
|
|
||||||
|`shutdown`
|
|`shutdown`
|
||||||
|Allows the application to be gracefully shutdown (not enabled by default).
|
|Allows the application to be gracefully shutdown (not enabled by default).
|
||||||
|true
|
|
||||||
|
|
||||||
|`trace`
|
|`trace`
|
||||||
|Displays trace information (by default the last 100 HTTP requests).
|
|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:
|
If you are using Spring MVC, the following additional endpoints can also be used:
|
||||||
|
|
||||||
[cols="2,5,1"]
|
[cols="2,5,1"]
|
||||||
|===
|
|===
|
||||||
| ID | Description | Sensitive Default
|
| ID | Description
|
||||||
|
|
||||||
|`heapdump`
|
|`heapdump`
|
||||||
|Returns a GZip compressed `hprof` heap dump file.
|
|Returns a GZip compressed `hprof` heap dump file.
|
||||||
|true
|
|
||||||
|
|
||||||
|`jolokia`
|
|`jolokia`
|
||||||
|Exposes JMX beans over HTTP (when Jolokia is on the classpath).
|
|Exposes JMX beans over HTTP (when Jolokia is on the classpath).
|
||||||
|true
|
|
||||||
|
|
||||||
|`logfile`
|
|`logfile`
|
||||||
|Returns the contents of the logfile (if `logging.file` or `logging.path` properties have
|
|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
|
been set). Supports the use of the HTTP `Range` header to retrieve part of the log file's
|
||||||
content.
|
content.
|
||||||
|true
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
NOTE: Depending on how an endpoint is exposed, the `sensitive` property may be used as
|
[[production-ready-endpoints-security]]
|
||||||
a security hint. For example, sensitive endpoints will require a username/password when
|
=== Securing endpoints
|
||||||
they are accessed over HTTP (or simply disabled if web security is not enabled).
|
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]]
|
[[production-ready-customizing-endpoints]]
|
||||||
=== Customizing endpoints
|
=== Customizing endpoints
|
||||||
Endpoints can be customized using Spring properties. You can change if an endpoint is
|
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
|
For example, here is an `application.properties` that changes the id of the `beans`
|
||||||
of the `beans` endpoint and also enables `shutdown`.
|
endpoint and also enables `shutdown`.
|
||||||
|
|
||||||
[source,properties,indent=0]
|
[source,properties,indent=0]
|
||||||
----
|
----
|
||||||
endpoints.beans.id=springbeans
|
endpoints.beans.id=springbeans
|
||||||
endpoints.beans.sensitive=false
|
|
||||||
endpoints.shutdown.enabled=true
|
endpoints.shutdown.enabled=true
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|
@ -188,16 +219,6 @@ For example, the following will disable _all_ endpoints except for `info`:
|
||||||
endpoints.info.enabled=true
|
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]]
|
[[production-ready-endpoint-hypermedia]]
|
||||||
|
|
@ -272,12 +293,6 @@ overall health status. If no `HealthIndicator` returns a status that is known to
|
||||||
|
|
||||||
|
|
||||||
=== Security with HealthIndicators
|
=== 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
|
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
|
`endpoints.health.time-to-live` property if you want to change the default cache period
|
||||||
of 1000 milliseconds.
|
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]]
|
[[production-ready-customizing-management-server-context-path]]
|
||||||
=== Customizing the management endpoint paths
|
=== Customizing the management endpoint paths
|
||||||
Sometimes it is useful to customize the prefix for the management endpoints.
|
Sometimes it is useful to customize the prefix for the management endpoints.
|
||||||
|
|
@ -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]]
|
[[production-ready-jmx]]
|
||||||
|
|
|
||||||
|
|
@ -50,14 +50,14 @@ public class CorsSampleActuatorApplicationTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sensitiveEndpointShouldReturnUnauthorized() throws Exception {
|
public void endpointShouldReturnUnauthorized() throws Exception {
|
||||||
ResponseEntity<?> entity = this.testRestTemplate.getForEntity("/application/env",
|
ResponseEntity<?> entity = this.testRestTemplate.getForEntity("/application/env",
|
||||||
Map.class);
|
Map.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void preflightRequestForInsensitiveShouldReturnOk() throws Exception {
|
public void preflightRequestToEndpointShouldReturnOk() throws Exception {
|
||||||
RequestEntity<?> healthRequest = RequestEntity
|
RequestEntity<?> healthRequest = RequestEntity
|
||||||
.options(new URI("/application/health"))
|
.options(new URI("/application/health"))
|
||||||
.header("Origin", "http://localhost:8080")
|
.header("Origin", "http://localhost:8080")
|
||||||
|
|
@ -67,15 +67,6 @@ public class CorsSampleActuatorApplicationTests {
|
||||||
assertThat(exchange.getStatusCode()).isEqualTo(HttpStatus.OK);
|
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
|
@Test
|
||||||
public void preflightRequestWhenCorsConfigInvalidShouldReturnForbidden()
|
public void preflightRequestWhenCorsConfigInvalidShouldReturnForbidden()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,9 @@ import java.util.Map;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.actuate.autoconfigure.LocalManagementPort;
|
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;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
|
@ -45,6 +47,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@DirtiesContext
|
@DirtiesContext
|
||||||
public class ManagementAddressActuatorApplicationTests {
|
public class ManagementAddressActuatorApplicationTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
private int port = 9010;
|
private int port = 9010;
|
||||||
|
|
||||||
|
|
@ -61,11 +66,16 @@ public class ManagementAddressActuatorApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
|
ResponseEntity<String> entity = new TestRestTemplate()
|
||||||
"http://localhost:" + this.managementPort + "/admin/health",
|
.withBasicAuth("user", getPassword())
|
||||||
|
.getForEntity("http://localhost:" + this.managementPort + "/admin/health",
|
||||||
String.class);
|
String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
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.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
|
@ -46,10 +47,14 @@ public class ManagementPathSampleActuatorApplicationTests {
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestRestTemplate restTemplate;
|
private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties securityProperties;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/admin/health",
|
ResponseEntity<String> entity = this.restTemplate
|
||||||
String.class);
|
.withBasicAuth("user", getPassword())
|
||||||
|
.getForEntity("/admin/health", String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||||
}
|
}
|
||||||
|
|
@ -65,4 +70,8 @@ public class ManagementPathSampleActuatorApplicationTests {
|
||||||
assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie");
|
assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPassword() {
|
||||||
|
return this.securityProperties.getUser().getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,9 @@ public class ManagementPortAndPathSampleActuatorApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
|
ResponseEntity<String> entity = new TestRestTemplate()
|
||||||
"http://localhost:" + this.managementPort + "/admin/health",
|
.withBasicAuth("user", getPassword())
|
||||||
|
.getForEntity("http://localhost:" + this.managementPort + "/admin/health",
|
||||||
String.class);
|
String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||||
|
|
|
||||||
|
|
@ -71,14 +71,17 @@ public class ManagementPortSampleActuatorApplicationTests {
|
||||||
testHome(); // makes sure some requests have been made
|
testHome(); // makes sure some requests have been made
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
|
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);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = new TestRestTemplate().getForEntity(
|
ResponseEntity<String> entity = new TestRestTemplate()
|
||||||
"http://localhost:" + this.managementPort + "/application/health", String.class);
|
.withBasicAuth("user", getPassword()).getForEntity(
|
||||||
|
"http://localhost:" + this.managementPort + "/application/health",
|
||||||
|
String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
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
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = this.restTemplate
|
ResponseEntity<String> entity = this.restTemplate
|
||||||
|
.withBasicAuth("user", getPassword())
|
||||||
.getForEntity("/application/health", String.class);
|
.getForEntity("/application/health", String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||||
assertThat(entity.getBody()).doesNotContain("\"hello\":\"1\"");
|
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
|
@Test
|
||||||
public void testInfo() throws Exception {
|
public void testInfo() throws Exception {
|
||||||
ResponseEntity<String> entity = this.restTemplate
|
ResponseEntity<String> entity = this.restTemplate
|
||||||
|
.withBasicAuth("user", getPassword())
|
||||||
.getForEntity("/application/info", String.class);
|
.getForEntity("/application/info", String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody())
|
assertThat(entity.getBody())
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
|
@ -46,6 +47,9 @@ public class ServletPathSampleActuatorApplicationTests {
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestRestTemplate restTemplate;
|
private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SecurityProperties security;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testErrorPath() throws Exception {
|
public void testErrorPath() throws Exception {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
|
@ -60,8 +64,9 @@ public class ServletPathSampleActuatorApplicationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHealth() throws Exception {
|
public void testHealth() throws Exception {
|
||||||
ResponseEntity<String> entity = this.restTemplate.getForEntity("/spring//application/health",
|
ResponseEntity<String> entity = this.restTemplate
|
||||||
String.class);
|
.withBasicAuth("user", getPassword())
|
||||||
|
.getForEntity("/spring/application/health", String.class);
|
||||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
|
||||||
}
|
}
|
||||||
|
|
@ -78,4 +83,8 @@ public class ServletPathSampleActuatorApplicationTests {
|
||||||
assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie");
|
assertThat(entity.getHeaders()).doesNotContainKey("Set-Cookie");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPassword() {
|
||||||
|
return this.security.getUser().getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue