mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Use endpoint mappings in CloudFoundry integration
Closes gh-35411
This commit is contained in:
parent
585286e472
commit
307f3c3399
@ -28,6 +28,7 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
@ -56,12 +57,15 @@ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointH
|
||||
|
||||
private final EndpointLinksResolver linksResolver;
|
||||
|
||||
private final Collection<ExposableEndpoint<?>> allEndpoints;
|
||||
|
||||
CloudFoundryWebFluxEndpointHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
Collection<ExposableEndpoint<?>> allEndpoints) {
|
||||
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, true);
|
||||
this.linksResolver = linksResolver;
|
||||
this.linksResolver = new EndpointLinksResolver(allEndpoints);
|
||||
this.allEndpoints = allEndpoints;
|
||||
this.securityInterceptor = securityInterceptor;
|
||||
}
|
||||
|
||||
@ -76,6 +80,10 @@ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointH
|
||||
return new CloudFoundryLinksHandler();
|
||||
}
|
||||
|
||||
Collection<ExposableEndpoint<?>> getAllEndpoints() {
|
||||
return this.allEndpoints;
|
||||
}
|
||||
|
||||
class CloudFoundryLinksHandler implements LinksHandler {
|
||||
|
||||
@Override
|
||||
|
@ -33,10 +33,10 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoC
|
||||
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
||||
@ -82,6 +82,8 @@ import org.springframework.web.server.WebFilter;
|
||||
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
|
||||
public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
|
||||
private static final String BASE_PATH = "/cloudfoundryapplication";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnAvailableEndpoint
|
||||
@ -117,9 +119,8 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
||||
allEndpoints.addAll(webEndpoints);
|
||||
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
|
||||
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
|
||||
new EndpointLinksResolver(allEndpoints));
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping(BASE_PATH), webEndpoints,
|
||||
endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
|
||||
}
|
||||
|
||||
private CloudFoundrySecurityInterceptor getSecurityInterceptor(WebClient.Builder webClientBuilder,
|
||||
@ -155,25 +156,33 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
static class IgnoredPathsSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
WebFilterChainPostProcessor webFilterChainPostProcessor() {
|
||||
return new WebFilterChainPostProcessor();
|
||||
WebFilterChainPostProcessor webFilterChainPostProcessor(
|
||||
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
|
||||
return new WebFilterChainPostProcessor(handlerMapping);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class WebFilterChainPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final PathMappedEndpoints pathMappedEndpoints;
|
||||
|
||||
WebFilterChainPostProcessor(CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
|
||||
this.pathMappedEndpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof WebFilterChainProxy) {
|
||||
return postProcess((WebFilterChainProxy) bean);
|
||||
return postProcess((WebFilterChainProxy) bean, this.pathMappedEndpoints);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
|
||||
private WebFilterChainProxy postProcess(WebFilterChainProxy existing, PathMappedEndpoints pathMappedEndpoints) {
|
||||
List<String> paths = getPaths(pathMappedEndpoints);
|
||||
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
|
||||
.pathMatchers("/cloudfoundryapplication/**");
|
||||
.pathMatchers(paths.toArray(new String[] {}));
|
||||
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
|
||||
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
|
||||
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
|
||||
@ -182,6 +191,14 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
||||
return new WebFilterChainProxy(ignoredRequestFilterChain, allRequestsFilterChain);
|
||||
}
|
||||
|
||||
private static List<String> getPaths(PathMappedEndpoints pathMappedEndpoints) {
|
||||
List<String> paths = new ArrayList<>();
|
||||
pathMappedEndpoints.getAllPaths().forEach((path) -> paths.add(path + "/**"));
|
||||
paths.add(BASE_PATH);
|
||||
paths.add(BASE_PATH + "/");
|
||||
return paths;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfi
|
||||
import org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;
|
||||
import org.springframework.boot.actuate.health.HealthEndpoint;
|
||||
@ -66,6 +66,9 @@ import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
|
||||
@ -86,6 +89,8 @@ import org.springframework.web.servlet.DispatcherServlet;
|
||||
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
|
||||
public class CloudFoundryActuatorAutoConfiguration {
|
||||
|
||||
private static final String BASE_PATH = "/cloudfoundryapplication";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnAvailableEndpoint
|
||||
@ -123,8 +128,7 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
|
||||
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
||||
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
|
||||
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
|
||||
new EndpointLinksResolver(allEndpoints));
|
||||
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
|
||||
}
|
||||
|
||||
private CloudFoundrySecurityInterceptor getSecurityInterceptor(RestTemplateBuilder restTemplateBuilder,
|
||||
@ -164,8 +168,9 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
public static class IgnoredCloudFoundryPathsWebSecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer() {
|
||||
return new IgnoredCloudFoundryPathsWebSecurityCustomizer();
|
||||
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer(
|
||||
CloudFoundryWebEndpointServletHandlerMapping handlerMapping) {
|
||||
return new IgnoredCloudFoundryPathsWebSecurityCustomizer(handlerMapping);
|
||||
}
|
||||
|
||||
}
|
||||
@ -173,9 +178,22 @@ public class CloudFoundryActuatorAutoConfiguration {
|
||||
@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) {
|
||||
web.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**"));
|
||||
List<RequestMatcher> requestMatchers = new ArrayList<>();
|
||||
this.pathMappedEndpoints.getAllPaths()
|
||||
.forEach((path) -> requestMatchers.add(new AntPathRequestMatcher(path + "/**")));
|
||||
requestMatchers.add(new AntPathRequestMatcher(BASE_PATH));
|
||||
requestMatchers.add(new AntPathRequestMatcher(BASE_PATH + "/"));
|
||||
if (!CollectionUtils.isEmpty(requestMatchers)) {
|
||||
web.ignoring().requestMatchers(new OrRequestMatcher(requestMatchers));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.SecurityResponse;
|
||||
import org.springframework.boot.actuate.endpoint.EndpointId;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
@ -60,13 +61,16 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
|
||||
|
||||
private final EndpointLinksResolver linksResolver;
|
||||
|
||||
private final Collection<ExposableEndpoint<?>> allEndpoints;
|
||||
|
||||
CloudFoundryWebEndpointServletHandlerMapping(EndpointMapping endpointMapping,
|
||||
Collection<ExposableWebEndpoint> endpoints, EndpointMediaTypes endpointMediaTypes,
|
||||
CorsConfiguration corsConfiguration, CloudFoundrySecurityInterceptor securityInterceptor,
|
||||
EndpointLinksResolver linksResolver) {
|
||||
Collection<ExposableEndpoint<?>> allEndpoints) {
|
||||
super(endpointMapping, endpoints, endpointMediaTypes, corsConfiguration, true);
|
||||
this.securityInterceptor = securityInterceptor;
|
||||
this.linksResolver = linksResolver;
|
||||
this.linksResolver = new EndpointLinksResolver(allEndpoints);
|
||||
this.allEndpoints = allEndpoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -80,6 +84,10 @@ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpoin
|
||||
return new CloudFoundryLinksHandler();
|
||||
}
|
||||
|
||||
Collection<ExposableEndpoint<?>> getAllEndpoints() {
|
||||
return this.allEndpoints;
|
||||
}
|
||||
|
||||
class CloudFoundryLinksHandler implements LinksHandler {
|
||||
|
||||
@Override
|
||||
|
@ -17,8 +17,11 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@ -28,15 +31,16 @@ import reactor.core.publisher.Mono;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration;
|
||||
@ -184,9 +188,10 @@ class CloudFoundryWebFluxEndpointIntegrationTests {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
|
||||
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointDiscoverer.getEndpoints();
|
||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>(webEndpoints);
|
||||
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"), webEndpoints,
|
||||
endpointMediaTypes, corsConfiguration, interceptor, allEndpoints);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
@ -95,6 +95,8 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
InfoContributorAutoConfiguration.class, InfoEndpointAutoConfiguration.class,
|
||||
ProjectInfoAutoConfiguration.class, ReactiveCloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
private static final String BASE_PATH = "/cloudfoundryapplication";
|
||||
|
||||
@AfterEach
|
||||
void close() {
|
||||
HttpResources.reset();
|
||||
@ -170,26 +172,36 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new).withPropertyValues("VCAP_APPLICATION:---",
|
||||
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
|
||||
.run((context) -> {
|
||||
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
|
||||
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
|
||||
.getField(chainProxy, "filters");
|
||||
Boolean cfRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
Boolean otherRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
Boolean cfBaseRequestMatches = getMatches(filters, BASE_PATH);
|
||||
Boolean cfBaseWithTrailingSlashRequestMatches = getMatches(filters, BASE_PATH + "/");
|
||||
Boolean cfRequestMatches = getMatches(filters, BASE_PATH + "/test");
|
||||
Boolean cfRequestWithAdditionalPathMatches = getMatches(filters, BASE_PATH + "/test/a");
|
||||
Boolean otherCfRequestMatches = getMatches(filters, BASE_PATH + "/other-path");
|
||||
Boolean otherRequestMatches = getMatches(filters, "/some-other-path");
|
||||
assertThat(cfBaseRequestMatches).isTrue();
|
||||
assertThat(cfBaseWithTrailingSlashRequestMatches).isTrue();
|
||||
assertThat(cfRequestMatches).isTrue();
|
||||
assertThat(cfRequestWithAdditionalPathMatches).isTrue();
|
||||
assertThat(otherCfRequestMatches).isFalse();
|
||||
assertThat(otherRequestMatches).isFalse();
|
||||
otherRequestMatches = filters.get(1)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
assertThat(otherRequestMatches).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
private static Boolean getMatches(List<SecurityWebFilterChain> filters, String urlTemplate) {
|
||||
Boolean cfBaseRequestMatches = filters.get(0)
|
||||
.matches(MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate).build()))
|
||||
.block(Duration.ofSeconds(30));
|
||||
return cfBaseRequestMatches;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,6 +77,8 @@ class CloudFoundryActuatorAutoConfigurationTests {
|
||||
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
|
||||
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
|
||||
|
||||
private static String BASE_PATH = "/cloudfoundryapplication";
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformActive() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
|
||||
@ -160,20 +162,31 @@ class CloudFoundryActuatorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
void cloudFoundryPathsIgnoredBySpringSecurity() {
|
||||
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
this.contextRunner.withBean(TestEndpoint.class, TestEndpoint::new)
|
||||
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
|
||||
.run((context) -> {
|
||||
FilterChainProxy securityFilterChain = (FilterChainProxy) context
|
||||
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
|
||||
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setServletPath("/cloudfoundryapplication/my-path");
|
||||
assertThat(chain.getFilters()).isEmpty();
|
||||
assertThat(chain.matches(request)).isTrue();
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
testCloudFoundrySecurity(request, BASE_PATH, chain);
|
||||
testCloudFoundrySecurity(request, BASE_PATH + "/", chain);
|
||||
testCloudFoundrySecurity(request, BASE_PATH + "/test", chain);
|
||||
testCloudFoundrySecurity(request, BASE_PATH + "/test/a", chain);
|
||||
request.setServletPath(BASE_PATH + "/other-path");
|
||||
assertThat(chain.matches(request)).isFalse();
|
||||
request.setServletPath("/some-other-path");
|
||||
assertThat(chain.matches(request)).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
private static void testCloudFoundrySecurity(MockHttpServletRequest request, String basePath,
|
||||
SecurityFilterChain chain) {
|
||||
request.setServletPath(basePath);
|
||||
assertThat(chain.matches(request)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void cloudFoundryPlatformInactive() {
|
||||
this.contextRunner.withPropertyValues()
|
||||
|
@ -17,8 +17,11 @@
|
||||
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.servlet;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
@ -28,15 +31,16 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.AccessLevel;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException;
|
||||
import org.springframework.boot.actuate.autoconfigure.cloudfoundry.CloudFoundryAuthorizationException.Reason;
|
||||
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.Selector;
|
||||
import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointLinksResolver;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMapping;
|
||||
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
||||
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
||||
import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpointDiscoverer;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
@ -180,9 +184,10 @@ class CloudFoundryMvcWebEndpointIntegrationTests {
|
||||
CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
|
||||
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
|
||||
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cfApplication"),
|
||||
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
|
||||
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
|
||||
Collection<ExposableWebEndpoint> webEndpoints = webEndpointDiscoverer.getEndpoints();
|
||||
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>(webEndpoints);
|
||||
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cfApplication"), webEndpoints,
|
||||
endpointMediaTypes, corsConfiguration, interceptor, allEndpoints);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
Loading…
Reference in New Issue
Block a user