Commit bacbe045 authored by Madhura Bhave's avatar Madhura Bhave

Disable web endpoints by default

Since the handler interceptors have been removed, web endpoints
are all disabled by default to prevent accidental exposure of
sensitive information.

Closes gh-7958
parent e08ddbf8
......@@ -103,6 +103,10 @@ public class EndpointEnablementProvider {
if (globalTypeOutcome != null) {
return globalTypeOutcome;
}
else if (!endpointType.isEnabledByDefault()) {
return new EndpointEnablement(false, createDefaultEnablementMessage("all", false,
endpointType));
}
}
else {
// Check if there is a global tech required
......
......@@ -184,6 +184,7 @@ public class ConditionalOnEnabledEndpointTests {
@Test
public void enabledOnlyWebByDefault() {
this.contextRunner.withUserConfiguration(OnlyWebConfig.class)
.withPropertyValues("endpoints.all.web.enabled=true")
.run((context) -> assertThat(context).hasBean("onlyweb"));
}
......
......@@ -55,56 +55,56 @@ public class WebMvcEndpointInfrastructureAutoConfigurationTests {
ServletEndpointAutoConfiguration.class));
@Test
public void webEndpointsAreExposed() {
this.contextRunner.run((context) -> {
public void webEndpointsAreDisabledByDefault() {
this.contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings"))
.isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace")).isTrue();
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace")).isFalse();
});
}
@Test
public void webEndpointsCanBeDisabled() {
public void webEndpointsCanBeEnabled() {
WebApplicationContextRunner contextRunner = this.contextRunner
.withPropertyValues("endpoints.all.web.enabled=false");
contextRunner.run((context) -> {
.withPropertyValues("endpoints.all.web.enabled=true");
contextRunner.run(context -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/autoconfig"))
.isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/beans"))
.isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/configprops"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/env")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/health"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/info")).isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/mappings"))
.isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/metrics"))
.isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.POST, "/application/shutdown"))
.isFalse();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/threaddump"))
.isFalse();
.isTrue();
assertThat(isExposed(mockMvc, HttpMethod.GET, "/application/trace"))
.isFalse();
.isTrue();
});
}
......
......@@ -185,8 +185,8 @@ public class EndpointEnablementProviderTests {
@Test
public void specificEnabledByDefault() {
validate(determineEnablement("foo", true, EndpointType.WEB), true,
"endpoint 'foo' (web) is enabled by default");
validate(determineEnablement("foo", true, EndpointType.JMX), true,
"endpoint 'foo' (jmx) is enabled by default");
}
@Test
......@@ -208,15 +208,15 @@ public class EndpointEnablementProviderTests {
@Test
public void specificNotDisabledViaUnrelatedTechProperty() {
validate(
determineEnablement("foo", true, EndpointType.WEB,
"endpoints.foo.jmx.enabled=false"),
true, "endpoint 'foo' (web) is enabled by default");
determineEnablement("foo", true, EndpointType.JMX,
"endpoints.foo.web.enabled=false"),
true, "endpoint 'foo' (jmx) is enabled by default");
}
@Test
public void specificDisabledViaGeneralProperty() {
validate(
determineEnablement("foo", true, EndpointType.WEB,
determineEnablement("foo", true, EndpointType.JMX,
"endpoints.all.enabled=false"),
false, "found property endpoints.all.enabled");
}
......@@ -256,8 +256,8 @@ public class EndpointEnablementProviderTests {
@Test
public void specificEnabledOverrideHasNoEffectWithUnrelatedTechProperty() {
validate(
determineEnablement("foo", true, EndpointType.WEB,
"endpoints.all.enabled=false", "endpoints.all.jmx.enabled=true"),
determineEnablement("foo", true, EndpointType.JMX,
"endpoints.all.enabled=false", "endpoints.all.web.enabled=true"),
false, "found property endpoints.all.enabled");
}
......
......@@ -161,7 +161,9 @@ public class WebEndpointManagementContextConfigurationTests {
}
private void beanIsAutoConfigured(Class<?> beanType, Class<?>... config) {
contextRunner().withUserConfiguration(config)
contextRunner()
.withPropertyValues("endpoints.all.web.enabled:true")
.withUserConfiguration(config)
.run((context) -> assertThat(context).hasSingleBean(beanType));
}
......
......@@ -65,6 +65,8 @@ public class MvcEndpointCorsIntegrationTests {
EndpointInfrastructureAutoConfiguration.class,
EndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletEndpointAutoConfiguration.class);
TestPropertyValues.of("endpoints.all.web.enabled:true")
.applyTo(this.context);
}
@Test
......
......@@ -79,6 +79,8 @@ import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
* {@link org.springframework.core.env.Environment} are reset at the end of every test.
* This means that {@link TestPropertyValues} can be used in a test without affecting the
* {@code Environment} of other tests in the same class.
* The runner always sets the flag `endpoints.all.web.enabled` to true so that web endpoints
* are enabled.
*
* @author Andy Wilkinson
*/
......@@ -190,6 +192,7 @@ public class WebEndpointsRunner extends Suite {
private MvcWebEndpointsRunner(Class<?> klass) throws InitializationError {
super(klass, "Spring MVC", (classes) -> {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();
TestPropertyValues.of("endpoints.all.web.enabled:true").applyTo(context);
classes.add(MvcTestConfiguration.class);
context.register(classes.toArray(new Class<?>[classes.size()]));
context.refresh();
......@@ -221,6 +224,7 @@ public class WebEndpointsRunner extends Suite {
private JerseyWebEndpointsRunner(Class<?> klass) throws InitializationError {
super(klass, "Jersey", (classes) -> {
AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();
TestPropertyValues.of("endpoints.all.web.enabled:true").applyTo(context);
classes.add(JerseyAppConfiguration.class);
classes.add(JerseyInfrastructureConfiguration.class);
context.register(classes.toArray(new Class<?>[classes.size()]));
......@@ -260,6 +264,7 @@ public class WebEndpointsRunner extends Suite {
private ReactiveWebEndpointsRunner(Class<?> klass) throws InitializationError {
super(klass, "Reactive", (classes) -> {
ReactiveWebServerApplicationContext context = new ReactiveWebServerApplicationContext();
TestPropertyValues.of("endpoints.all.web.enabled:true").applyTo(context);
classes.add(ReactiveInfrastructureConfiguration.class);
context.register(classes.toArray(new Class<?>[classes.size()]));
context.refresh();
......
......@@ -27,11 +27,20 @@ public enum EndpointType {
/**
* Expose the endpoint as a JMX MBean.
*/
JMX,
JMX(true),
/**
* Expose the endpoint as a Web endpoint.
*/
WEB
WEB(false);
private final boolean enabledByDefault;
EndpointType(boolean enabledByDefault) {
this.enabledByDefault = enabledByDefault;
}
public boolean isEnabledByDefault() {
return this.enabledByDefault;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment