From a148983e7fe8ae58064390e7d64f3fa70f38e878 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 16 Mar 2026 16:53:54 +0000 Subject: [PATCH] Polish "Fix EndpointRequest links matching for separate management port" See gh-49591 Signed-off-by: Andy Wilkinson --- .../security/reactive/EndpointRequest.java | 5 +- .../security/servlet/EndpointRequest.java | 2 +- .../reactive/EndpointRequestTests.java | 30 +++----- .../servlet/EndpointRequestTests.java | 30 +++----- ...ractSampleActuatorCustomSecurityTests.java | 74 ++++++++---------- .../CustomServletPathSampleActuatorTests.java | 4 +- ...asePathSampleActuatorApplicationTests.java | 77 +++++++++++++++++++ ...sePathSampleActuatorApplicationTests.java} | 12 +-- ...CustomServletPathSampleActuatorTests.java} | 10 +-- ...ctuatorCustomSecurityApplicationTests.java | 9 +-- 10 files changed, 146 insertions(+), 107 deletions(-) create mode 100644 spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathAndWebEndpointsBasePathSampleActuatorApplicationTests.java rename spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/{ManagementPortAndPathSampleActuatorApplicationTests.java => ManagementServerWithCustomBasePathSampleActuatorApplicationTests.java} (85%) rename spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/{ManagementPortCustomServletPathSampleActuatorTests.java => ManagementServerWithCustomServletPathSampleActuatorTests.java} (86%) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java index dcaad8d5564..5e09360669b 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequest.java @@ -374,10 +374,7 @@ public final class EndpointRequest { if (linksPath != null) { List linksMatchers = new ArrayList<>(); linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath)); - if ("/".equals(linksPath)) { - linksMatchers.add(new PathPatternParserServerWebExchangeMatcher("")); - } - else { + if (!linksPath.endsWith("/")) { linksMatchers.add(new PathPatternParserServerWebExchangeMatcher(linksPath + "/")); } return new OrServerWebExchangeMatcher(linksMatchers); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java index e8a16bd185a..f0e5f28734e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequest.java @@ -228,7 +228,7 @@ public final class EndpointRequest { RequestMatcherProvider matcherProvider, String linksPath) { List linksMatchers = new ArrayList<>(); linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, linksPath)); - if (!"/".equals(linksPath)) { + if (!linksPath.endsWith("/")) { linksMatchers.add(requestMatcherFactory.antPath(matcherProvider, null, linksPath, "/")); } return linksMatchers; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java index c1fbc54c65e..151ea82b28c 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/reactive/EndpointRequestTests.java @@ -20,7 +20,6 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import org.assertj.core.api.AssertDelegateTarget; import org.junit.jupiter.api.Test; @@ -33,10 +32,10 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; +import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.context.WebServerApplicationContext; import org.springframework.boot.web.server.WebServer; import org.springframework.context.support.StaticApplicationContext; -import org.springframework.core.env.MapPropertySource; import org.springframework.http.HttpMethod; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; @@ -97,7 +96,7 @@ class EndpointRequestTests { void toAnyEndpointWhenBasePathIsEmptyAndManagementPortDifferentShouldMatchLinks() { ServerWebExchangeMatcher matcher = EndpointRequest.toAnyEndpoint(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), - WebServerNamespace.MANAGEMENT, true); + WebServerNamespace.MANAGEMENT); assertMatcher.matches("/"); assertMatcher.matches("/foo"); } @@ -158,7 +157,7 @@ class EndpointRequestTests { void toLinksWhenBasePathEmptyAndManagementPortDifferentShouldMatchRoot() { ServerWebExchangeMatcher matcher = EndpointRequest.toLinks(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), - WebServerNamespace.MANAGEMENT, true); + WebServerNamespace.MANAGEMENT); assertMatcher.matches("/"); assertMatcher.doesNotMatch("/foo"); } @@ -345,25 +344,14 @@ class EndpointRequestTests { private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher, PathMappedEndpoints pathMappedEndpoints, WebServerNamespace namespace) { - return assertMatcher(matcher, pathMappedEndpoints, namespace, false); - } - - private RequestMatcherAssert assertMatcher(ServerWebExchangeMatcher matcher, - PathMappedEndpoints pathMappedEndpoints, WebServerNamespace namespace, boolean managementPortDifferent) { - StaticApplicationContext context = new StaticApplicationContext(); + StaticWebApplicationContext context; if (namespace != null && !WebServerNamespace.SERVER.equals(namespace)) { - if (managementPortDifferent) { - context = new NamedStaticWebApplicationContext(namespace); - } - else { - NamedStaticWebApplicationContext parentContext = new NamedStaticWebApplicationContext(namespace); - context.setParent(parentContext); - } + context = new NamedStaticWebApplicationContext(namespace); + context.setParent(new StaticWebApplicationContext()); + TestPropertyValues.of("management.server.port=0").applyTo(context); } - if (managementPortDifferent) { - context.getEnvironment() - .getPropertySources() - .addFirst(new MapPropertySource("test", Map.of("management.server.port", 0))); + else { + context = new StaticWebApplicationContext(); } context.registerBean(WebEndpointProperties.class); if (pathMappedEndpoints != null) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java index 6e1c21029e9..7a7620f2564 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/security/servlet/EndpointRequestTests.java @@ -19,7 +19,6 @@ package org.springframework.boot.actuate.autoconfigure.security.servlet; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import jakarta.servlet.http.HttpServletRequest; import org.assertj.core.api.AssertDelegateTarget; @@ -35,9 +34,9 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint; import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; import org.springframework.boot.actuate.endpoint.web.WebServerNamespace; +import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.web.context.WebServerApplicationContext; import org.springframework.boot.web.server.WebServer; -import org.springframework.core.env.MapPropertySource; import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockServletContext; @@ -97,7 +96,7 @@ class EndpointRequestTests { void toAnyEndpointWhenBasePathIsEmptyAndManagementPortDifferentShouldMatchLinks() { RequestMatcher matcher = EndpointRequest.toAnyEndpoint(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), null, - WebServerNamespace.MANAGEMENT, true); + WebServerNamespace.MANAGEMENT); assertMatcher.matches("/"); assertMatcher.matches("/foo"); } @@ -165,7 +164,7 @@ class EndpointRequestTests { void toLinksWhenBasePathEmptyAndManagementPortDifferentShouldMatchRoot() { RequestMatcher matcher = EndpointRequest.toLinks(); RequestMatcherAssert assertMatcher = assertMatcher(matcher, mockPathMappedEndpoints(""), null, - WebServerNamespace.MANAGEMENT, true); + WebServerNamespace.MANAGEMENT); assertMatcher.matches("/"); assertMatcher.doesNotMatch("/foo"); } @@ -370,25 +369,14 @@ class EndpointRequestTests { private RequestMatcherAssert assertMatcher(RequestMatcher matcher, PathMappedEndpoints pathMappedEndpoints, RequestMatcherProvider matcherProvider, WebServerNamespace namespace) { - return assertMatcher(matcher, pathMappedEndpoints, matcherProvider, namespace, false); - } - - private RequestMatcherAssert assertMatcher(RequestMatcher matcher, PathMappedEndpoints pathMappedEndpoints, - RequestMatcherProvider matcherProvider, WebServerNamespace namespace, boolean managementPortDifferent) { - StaticWebApplicationContext context = new StaticWebApplicationContext(); + StaticWebApplicationContext context; if (namespace != null && !WebServerNamespace.SERVER.equals(namespace)) { - if (managementPortDifferent) { - context = new NamedStaticWebApplicationContext(namespace); - } - else { - NamedStaticWebApplicationContext parentContext = new NamedStaticWebApplicationContext(namespace); - context.setParent(parentContext); - } + context = new NamedStaticWebApplicationContext(namespace); + context.setParent(new StaticWebApplicationContext()); + TestPropertyValues.of("management.server.port=0").applyTo(context); } - if (managementPortDifferent) { - context.getEnvironment() - .getPropertySources() - .addFirst(new MapPropertySource("test", Map.of("management.server.port", 0))); + else { + context = new StaticWebApplicationContext(); } context.registerBean(WebEndpointProperties.class); if (pathMappedEndpoints != null) { diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java index bc9f315fd36..7abb0283fe8 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/AbstractSampleActuatorCustomSecurityTests.java @@ -37,7 +37,7 @@ abstract class AbstractSampleActuatorCustomSecurityTests { abstract String getPath(); - abstract String getManagementPath(); + abstract String getActuatorPath(); abstract Environment getEnvironment(); @@ -58,119 +58,110 @@ abstract class AbstractSampleActuatorCustomSecurityTests { @Test void actuatorInsecureEndpoint() { - ResponseEntity entity = restTemplate().getForEntity(getManagementPath() + "/actuator/health", - String.class); + ResponseEntity entity = restTemplate().getForEntity(getActuatorPath() + "/health", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); - entity = restTemplate().getForEntity(getManagementPath() + "/actuator/health/diskSpace", String.class); + entity = restTemplate().getForEntity(getActuatorPath() + "/health/diskSpace", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).contains("\"status\":\"UP\""); } @Test void actuatorLinksWithAnonymous() { - ResponseEntity entity = restTemplate().getForEntity(getManagementPath() + "/actuator", Object.class); + ResponseEntity entity = restTemplate().getForEntity(getActuatorPath(), Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - entity = restTemplate().getForEntity(getManagementPath() + "/actuator/", Object.class); + entity = restTemplate().getForEntity(getActuatorPath() + "/", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test void actuatorLinksWithUnauthorizedUser() { - ResponseEntity entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator", - Object.class); + ResponseEntity entity = userRestTemplate().getForEntity(getActuatorPath(), Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator/", Object.class); + entity = userRestTemplate().getForEntity(getActuatorPath() + "/", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); } @Test void actuatorLinksWithAuthorizedUser() { - ResponseEntity entity = adminRestTemplate().getForEntity(getManagementPath() + "/actuator", - Object.class); + ResponseEntity entity = adminRestTemplate().getForEntity(getActuatorPath(), Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - adminRestTemplate().getForEntity(getManagementPath() + "/actuator/", Object.class); + adminRestTemplate().getForEntity(getActuatorPath() + "/", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } @Test void actuatorSecureEndpointWithAnonymous() { - ResponseEntity entity = restTemplate().getForEntity(getManagementPath() + "/actuator/env", - Object.class); + ResponseEntity entity = restTemplate().getForEntity(getActuatorPath() + "/env", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - entity = restTemplate().getForEntity( - getManagementPath() + "/actuator/env/management.endpoints.web.exposure.include", Object.class); + entity = restTemplate().getForEntity(getActuatorPath() + "/env/management.endpoints.web.exposure.include", + Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test void actuatorSecureEndpointWithUnauthorizedUser() { - ResponseEntity entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator/env", - Object.class); + ResponseEntity entity = userRestTemplate().getForEntity(getActuatorPath() + "/env", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - entity = userRestTemplate().getForEntity( - getManagementPath() + "/actuator/env/management.endpoints.web.exposure.include", Object.class); + entity = userRestTemplate().getForEntity(getActuatorPath() + "/env/management.endpoints.web.exposure.include", + Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); } @Test void actuatorSecureEndpointWithAuthorizedUser() { - ResponseEntity entity = adminRestTemplate().getForEntity(getManagementPath() + "/actuator/env", - Object.class); + ResponseEntity entity = adminRestTemplate().getForEntity(getActuatorPath() + "/env", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - entity = adminRestTemplate().getForEntity(getManagementPath() + "/actuator/env/", Object.class); + entity = adminRestTemplate().getForEntity(getActuatorPath() + "/env/", Object.class); // EndpointRequest matches the trailing slash but MVC doesn't assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - entity = adminRestTemplate().getForEntity( - getManagementPath() + "/actuator/env/management.endpoints.web.exposure.include", Object.class); + entity = adminRestTemplate().getForEntity(getActuatorPath() + "/env/management.endpoints.web.exposure.include", + Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } @Test void secureServletEndpointWithAnonymous() { - ResponseEntity entity = restTemplate().getForEntity(getManagementPath() + "/actuator/se1", - String.class); + ResponseEntity entity = restTemplate().getForEntity(getActuatorPath() + "/se1", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - entity = restTemplate().getForEntity(getManagementPath() + "/actuator/se1/list", String.class); + entity = restTemplate().getForEntity(getActuatorPath() + "/se1/list", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test void secureServletEndpointWithUnauthorizedUser() { - ResponseEntity entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator/se1", - String.class); + ResponseEntity entity = userRestTemplate().getForEntity(getActuatorPath() + "/se1", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator/se1/list", String.class); + entity = userRestTemplate().getForEntity(getActuatorPath() + "/se1/list", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); } @Test void secureServletEndpointWithAuthorizedUser() { - ResponseEntity entity = adminRestTemplate().getForEntity(getManagementPath() + "/actuator/se1", - String.class); + ResponseEntity entity = adminRestTemplate().getForEntity(getActuatorPath() + "/se1", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - entity = adminRestTemplate().getForEntity(getManagementPath() + "/actuator/se1/list", String.class); + entity = adminRestTemplate().getForEntity(getActuatorPath() + "/se1/list", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } @Test void actuatorCustomMvcSecureEndpointWithAnonymous() { - ResponseEntity entity = restTemplate() - .getForEntity(getManagementPath() + "/actuator/example/echo?text={t}", String.class, "test"); + ResponseEntity entity = restTemplate().getForEntity(getActuatorPath() + "/example/echo?text={t}", + String.class, "test"); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test void actuatorCustomMvcSecureEndpointWithUnauthorizedUser() { - ResponseEntity entity = userRestTemplate() - .getForEntity(getManagementPath() + "/actuator/example/echo?text={t}", String.class, "test"); + ResponseEntity entity = userRestTemplate().getForEntity(getActuatorPath() + "/example/echo?text={t}", + String.class, "test"); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); } @Test void actuatorCustomMvcSecureEndpointWithAuthorizedUser() { - ResponseEntity entity = adminRestTemplate() - .getForEntity(getManagementPath() + "/actuator/example/echo?text={t}", String.class, "test"); + ResponseEntity entity = adminRestTemplate().getForEntity(getActuatorPath() + "/example/echo?text={t}", + String.class, "test"); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); assertThat(entity.getBody()).isEqualTo("test"); assertThat(entity.getHeaders().getFirst("echo")).isEqualTo("test"); @@ -178,8 +169,7 @@ abstract class AbstractSampleActuatorCustomSecurityTests { @Test void actuatorExcludedFromEndpointRequestMatcher() { - ResponseEntity entity = userRestTemplate().getForEntity(getManagementPath() + "/actuator/mappings", - Object.class); + ResponseEntity entity = userRestTemplate().getForEntity(getActuatorPath() + "/mappings", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CustomServletPathSampleActuatorTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CustomServletPathSampleActuatorTests.java index ebc95a8a2bf..7dda1f9e907 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CustomServletPathSampleActuatorTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/CustomServletPathSampleActuatorTests.java @@ -42,8 +42,8 @@ class CustomServletPathSampleActuatorTests extends AbstractSampleActuatorCustomS } @Override - String getManagementPath() { - return "http://localhost:" + this.port + "/example"; + String getActuatorPath() { + return "http://localhost:" + this.port + "/example/actuator"; } @Override diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathAndWebEndpointsBasePathSampleActuatorApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathAndWebEndpointsBasePathSampleActuatorApplicationTests.java new file mode 100644 index 00000000000..636a59291ab --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathAndWebEndpointsBasePathSampleActuatorApplicationTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2012-present 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.customsecurity; + +import org.junit.jupiter.api.Test; + +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.boot.test.web.server.LocalManagementPort; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Integration tests for a separate management server with custom base path and web + * endpoints base path. + * + * @author Dave Syer + * @author Madhura Bhave + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "management.server.port=0", + "management.server.base-path=/management", "management.endpoints.web.base-path=/" }) +class ManagementServerWithCustomBasePathAndWebEndpointsBasePathSampleActuatorApplicationTests + extends AbstractSampleActuatorCustomSecurityTests { + + @LocalServerPort + private int port; + + @LocalManagementPort + private int managementPort; + + @Autowired + private Environment environment; + + @Test + void testMissing() { + ResponseEntity entity = new TestRestTemplate("admin", "admin") + .getForEntity(getActuatorPath() + "/missing", String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + assertThat(entity.getBody()).contains("\"status\":404"); + } + + @Override + String getPath() { + return "http://localhost:" + this.port; + } + + @Override + String getActuatorPath() { + return "http://localhost:" + this.managementPort + "/management"; + } + + @Override + Environment getEnvironment() { + return this.environment; + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortAndPathSampleActuatorApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathSampleActuatorApplicationTests.java similarity index 85% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortAndPathSampleActuatorApplicationTests.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathSampleActuatorApplicationTests.java index aa08feef9ee..353902eedbc 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortAndPathSampleActuatorApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomBasePathSampleActuatorApplicationTests.java @@ -31,15 +31,15 @@ import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; /** - * Integration tests for separate management and main service ports with custom management - * context path. + * Integration tests for a separate management server with a custom base path. * * @author Dave Syer * @author Madhura Bhave */ @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "management.server.port=0", "management.server.base-path=/management" }) -class ManagementPortAndPathSampleActuatorApplicationTests extends AbstractSampleActuatorCustomSecurityTests { +class ManagementServerWithCustomBasePathSampleActuatorApplicationTests + extends AbstractSampleActuatorCustomSecurityTests { @LocalServerPort private int port; @@ -53,7 +53,7 @@ class ManagementPortAndPathSampleActuatorApplicationTests extends AbstractSample @Test void testMissing() { ResponseEntity entity = new TestRestTemplate("admin", "admin") - .getForEntity("http://localhost:" + this.managementPort + "/management/actuator/missing", String.class); + .getForEntity(getActuatorPath() + "/missing", String.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); assertThat(entity.getBody()).contains("\"status\":404"); } @@ -64,8 +64,8 @@ class ManagementPortAndPathSampleActuatorApplicationTests extends AbstractSample } @Override - String getManagementPath() { - return "http://localhost:" + this.managementPort + "/management"; + String getActuatorPath() { + return "http://localhost:" + this.managementPort + "/management/actuator"; } @Override diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortCustomServletPathSampleActuatorTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomServletPathSampleActuatorTests.java similarity index 86% rename from spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortCustomServletPathSampleActuatorTests.java rename to spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomServletPathSampleActuatorTests.java index da042e70995..2fb5aea4684 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementPortCustomServletPathSampleActuatorTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/ManagementServerWithCustomServletPathSampleActuatorTests.java @@ -30,14 +30,14 @@ import org.springframework.http.ResponseEntity; import static org.assertj.core.api.Assertions.assertThat; /** - * Integration tests for separate management and main service ports with custom dispatcher - * servlet path. + * Integration tests for a separate management server with a custom dispatcher servlet + * path. * * @author Madhura Bhave */ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "management.server.port=0", "spring.mvc.servlet.path=/example" }) -class ManagementPortCustomServletPathSampleActuatorTests extends AbstractSampleActuatorCustomSecurityTests { +class ManagementServerWithCustomServletPathSampleActuatorTests extends AbstractSampleActuatorCustomSecurityTests { @LocalServerPort private int port; @@ -61,8 +61,8 @@ class ManagementPortCustomServletPathSampleActuatorTests extends AbstractSampleA } @Override - String getManagementPath() { - return "http://localhost:" + this.managementPort; + String getActuatorPath() { + return "http://localhost:" + this.managementPort + "/actuator"; } @Override diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/SampleActuatorCustomSecurityApplicationTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/SampleActuatorCustomSecurityApplicationTests.java index 7227fa42028..4be29ed6cee 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/SampleActuatorCustomSecurityApplicationTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-actuator-custom-security/src/test/java/smoketest/actuator/customsecurity/SampleActuatorCustomSecurityApplicationTests.java @@ -52,8 +52,8 @@ class SampleActuatorCustomSecurityApplicationTests extends AbstractSampleActuato } @Override - String getManagementPath() { - return "http://localhost:" + this.port; + String getActuatorPath() { + return "http://localhost:" + this.port + "/actuator"; } @Override @@ -72,10 +72,9 @@ class SampleActuatorCustomSecurityApplicationTests extends AbstractSampleActuato @Test void mvcMatchersCanBeUsedToSecureActuators() { - ResponseEntity entity = beansRestTemplate().getForEntity(getManagementPath() + "/actuator/beans", - Object.class); + ResponseEntity entity = beansRestTemplate().getForEntity(getActuatorPath() + "/beans", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); - entity = beansRestTemplate().getForEntity(getManagementPath() + "/actuator/beans/", Object.class); + entity = beansRestTemplate().getForEntity(getActuatorPath() + "/beans/", Object.class); assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); }