From 0386fbeb166e5da21ebd6f0cecf578e0321ad087 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 6 May 2025 12:28:46 -0700 Subject: [PATCH] Don't use the 'ignoring()' method in CloudFoundry security Update `IgnoredCloudFoundryPathsWebSecurityConfiguration` to use a `SecurityFilterChain` and `permit...` methods rather than `ignoring()` which is no longer recommended. Fixes gh-32622 --- ...CloudFoundryActuatorAutoConfiguration.java | 36 +++++++++---------- ...FoundryActuatorAutoConfigurationTests.java | 1 - .../security/SecurityProperties.java | 3 ++ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.java index ab4405f3b6..fc9bbf7ee7 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfiguration.java @@ -48,7 +48,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnCloudPlatform; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.cloud.CloudPlatform; import org.springframework.boot.info.GitProperties; import org.springframework.boot.web.client.RestTemplateBuilder; @@ -60,8 +59,10 @@ import org.springframework.core.env.Environment; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.WebSecurityConfigurer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.util.matcher.OrRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; @@ -158,7 +159,7 @@ public class CloudFoundryActuatorAutoConfiguration { } /** - * {@link WebSecurityConfigurer} to tell Spring Security to ignore cloudfoundry + * {@link WebSecurityConfigurer} to tell Spring Security to permit cloudfoundry * specific paths. The Cloud foundry endpoints are protected by their own security * interceptor. */ @@ -166,30 +167,25 @@ public class CloudFoundryActuatorAutoConfiguration { @Configuration(proxyBeanMethods = false) public static class IgnoredCloudFoundryPathsWebSecurityConfiguration { + private static final int FILTER_CHAIN_ORDER = -1; + @Bean - IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer( - CloudFoundryWebEndpointServletHandlerMapping handlerMapping) { - return new IgnoredCloudFoundryPathsWebSecurityCustomizer(handlerMapping); + @Order(FILTER_CHAIN_ORDER) + SecurityFilterChain cloudFoundrySecurityFilterChain(HttpSecurity http, + CloudFoundryWebEndpointServletHandlerMapping handlerMapping) throws Exception { + RequestMatcher cloudFoundryRequest = getRequestMatcher(handlerMapping); + http.securityMatchers((matches) -> matches.requestMatchers(cloudFoundryRequest)) + .authorizeHttpRequests((authorize) -> authorize.anyRequest().permitAll()); + return http.build(); } - } - - @Order(SecurityProperties.IGNORED_ORDER) - static class IgnoredCloudFoundryPathsWebSecurityCustomizer implements WebSecurityCustomizer { - - private final PathMappedEndpoints pathMappedEndpoints; - - IgnoredCloudFoundryPathsWebSecurityCustomizer(CloudFoundryWebEndpointServletHandlerMapping handlerMapping) { - this.pathMappedEndpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints); - } - - @Override - public void customize(WebSecurity web) { + private RequestMatcher getRequestMatcher(CloudFoundryWebEndpointServletHandlerMapping handlerMapping) { + PathMappedEndpoints endpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints); List matchers = new ArrayList<>(); - this.pathMappedEndpoints.getAllPaths().forEach((path) -> matchers.add(pathMatcher(path + "/**"))); + endpoints.getAllPaths().forEach((path) -> matchers.add(pathMatcher(path + "/**"))); matchers.add(pathMatcher(BASE_PATH)); matchers.add(pathMatcher(BASE_PATH + "/")); - web.ignoring().requestMatchers(new OrRequestMatcher(matchers)); + return new OrRequestMatcher(matchers); } private PathPatternRequestMatcher pathMatcher(String path) { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfigurationTests.java index d5dbe6f481..90c0c43998 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryActuatorAutoConfigurationTests.java @@ -175,7 +175,6 @@ class CloudFoundryActuatorAutoConfigurationTests { .withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") .run((context) -> { SecurityFilterChain chain = getSecurityFilterChain(context); - assertThat(chain.getFilters()).isEmpty(); MockHttpServletRequest request = new MockHttpServletRequest(); testCloudFoundrySecurity(request, BASE_PATH, chain); testCloudFoundrySecurity(request, BASE_PATH + "/", chain); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java index 69bcbe7557..934288f50f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java @@ -50,7 +50,10 @@ public class SecurityProperties { /** * Order applied to the {@code WebSecurityCustomizer} that ignores standard static * resource paths. + * @deprecated since 3.5.0 for removal in 4.0.0 since Spring Security no longer + * recommends using the {@code .ignoring()} method */ + @Deprecated(since = "3.5.0", forRemoval = true) public static final int IGNORED_ORDER = Ordered.HIGHEST_PRECEDENCE; /**