Browse Source

Merge pull request #45251 from YongGoose

* pr/45251:
  Polish 'Fail fast when base path and an endpoint mapping are set to '/''
  Fail fast when base path and an endpoint mapping are set to '/'

Closes gh-45251
pull/45268/head
Phillip Webb 10 months ago
parent
commit
82a2cbbe75
  1. 35
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointAutoConfiguration.java
  2. 2
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.java
  3. 5
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration.java
  4. 5
      spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/DiscoveredWebEndpoint.java
  5. 42
      spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/ManagementEndpointConflictSmokeTests.java

35
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/WebEndpointAutoConfiguration.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@ -23,6 +23,7 @@ import org.springframework.beans.factory.ObjectProvider; @@ -23,6 +23,7 @@ import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure;
import org.springframework.boot.actuate.autoconfigure.endpoint.expose.IncludeExcludeEndpointFilter;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;
import org.springframework.boot.actuate.endpoint.EndpointAccessResolver;
import org.springframework.boot.actuate.endpoint.EndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
@ -33,10 +34,12 @@ import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper; @@ -33,10 +34,12 @@ import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
import org.springframework.boot.actuate.endpoint.web.AdditionalPathsMapper;
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
import org.springframework.boot.actuate.endpoint.web.PathMapper;
import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier;
import org.springframework.boot.actuate.endpoint.web.WebOperation;
import org.springframework.boot.actuate.endpoint.web.WebServerNamespace;
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -47,6 +50,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties @@ -47,6 +50,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link EnableAutoConfiguration Auto-configuration} for web {@link Endpoint @Endpoint}
@ -54,6 +59,7 @@ import org.springframework.context.annotation.Configuration; @@ -54,6 +59,7 @@ import org.springframework.context.annotation.Configuration;
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Yongjun Hong
* @since 2.0.0
*/
@AutoConfiguration(after = EndpointAutoConfiguration.class)
@ -109,7 +115,32 @@ public class WebEndpointAutoConfiguration { @@ -109,7 +115,32 @@ public class WebEndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public PathMappedEndpoints pathMappedEndpoints(Collection<EndpointsSupplier<?>> endpointSuppliers) {
return new PathMappedEndpoints(this.properties.getBasePath(), endpointSuppliers);
String basePath = this.properties.getBasePath();
PathMappedEndpoints pathMappedEndpoints = new PathMappedEndpoints(basePath, endpointSuppliers);
if ((!StringUtils.hasText(basePath) || "/".equals(basePath))
&& ManagementPortType.get(this.applicationContext.getEnvironment()) == ManagementPortType.SAME) {
assertHasNoRootPaths(pathMappedEndpoints);
}
return pathMappedEndpoints;
}
private void assertHasNoRootPaths(PathMappedEndpoints endpoints) {
for (PathMappedEndpoint endpoint : endpoints) {
if (endpoint instanceof ExposableWebEndpoint webEndpoint) {
Assert.state(!isMappedToRootPath(webEndpoint),
() -> "Management base path and the '" + webEndpoint.getEndpointId()
+ "' actuator endpoint are both mapped to '/' "
+ "on the server port which will block access to other endpoints. "
+ "Please use a different path for management endpoints or map them to a "
+ "dedicated management port.");
}
}
}
private boolean isMappedToRootPath(PathMappedEndpoint endpoint) {
return endpoint.getRootPath().equals("/")
|| endpoint.getAdditionalPaths(WebServerNamespace.SERVER).contains("/");
}
@Bean

2
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/web/servlet/WebMvcEndpointManagementContextConfiguration.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.

5
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@ -17,7 +17,6 @@ @@ -17,7 +17,6 @@
package org.springframework.boot.actuate.autoconfigure.web.server;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextFactory;
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
import org.springframework.boot.autoconfigure.AutoConfiguration;
@ -45,7 +44,7 @@ import org.springframework.util.Assert; @@ -45,7 +44,7 @@ import org.springframework.util.Assert;
*/
@AutoConfiguration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties({ WebEndpointProperties.class, ManagementServerProperties.class })
@EnableConfigurationProperties(ManagementServerProperties.class)
public class ManagementContextAutoConfiguration {
@Configuration(proxyBeanMethods = false)

5
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/annotation/DiscoveredWebEndpoint.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@ -61,7 +61,8 @@ class DiscoveredWebEndpoint extends AbstractDiscoveredEndpoint<WebOperation> imp @@ -61,7 +61,8 @@ class DiscoveredWebEndpoint extends AbstractDiscoveredEndpoint<WebOperation> imp
}
private Stream<String> getAdditionalPaths(WebServerNamespace webServerNamespace, AdditionalPathsMapper mapper) {
return mapper.getAdditionalPaths(getEndpointId(), webServerNamespace).stream();
List<String> additionalPaths = mapper.getAdditionalPaths(getEndpointId(), webServerNamespace);
return (additionalPaths != null) ? additionalPaths.stream() : Stream.empty();
}
}

42
spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/ManagementEndpointConflictSmokeTests.java

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
/*
* Copyright 2012-2025 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
*
* https://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 smoketest.actuator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.SpringApplication;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Verifies that an exception is thrown when management and server endpoint paths
* conflict.
*
* @author Yongjun Hong
*/
class ManagementEndpointConflictSmokeTests {
@Test
void shouldThrowExceptionWhenManagementAndServerPathsConflict() {
assertThatExceptionOfType(BeanCreationException.class)
.isThrownBy(() -> SpringApplication.run(SampleActuatorApplication.class,
"--management.endpoints.web.base-path=/", "--management.endpoints.web.path-mapping.health=/"))
.withMessageContaining("Management base path and the 'health' actuator endpoint are both mapped to '/'");
}
}
Loading…
Cancel
Save