|
|
@ -32,10 +32,10 @@ import org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoC
|
|
|
|
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
|
|
|
|
import org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration;
|
|
|
|
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
|
|
|
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
|
|
|
|
import org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper;
|
|
|
|
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.EndpointMapping;
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes;
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint;
|
|
|
|
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.ControllerEndpointsSupplier;
|
|
|
|
import org.springframework.boot.actuate.health.HealthEndpoint;
|
|
|
|
import org.springframework.boot.actuate.health.HealthEndpoint;
|
|
|
|
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
|
|
|
import org.springframework.boot.actuate.health.ReactiveHealthEndpointWebExtension;
|
|
|
@ -80,6 +80,8 @@ import org.springframework.web.server.WebFilter;
|
|
|
|
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
|
|
|
|
@ConditionalOnCloudPlatform(CloudPlatform.CLOUD_FOUNDRY)
|
|
|
|
public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
|
|
|
public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final String BASE_PATH = "/cloudfoundryapplication";
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
|
@ConditionalOnMissingBean
|
|
|
|
@ConditionalOnMissingBean
|
|
|
|
@ConditionalOnAvailableEndpoint
|
|
|
|
@ConditionalOnAvailableEndpoint
|
|
|
@ -115,9 +117,8 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
|
|
|
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
|
|
|
List<ExposableEndpoint<?>> allEndpoints = new ArrayList<>();
|
|
|
|
allEndpoints.addAll(webEndpoints);
|
|
|
|
allEndpoints.addAll(webEndpoints);
|
|
|
|
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
|
|
|
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
|
|
|
|
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cloudfoundryapplication"),
|
|
|
|
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping(BASE_PATH), webEndpoints,
|
|
|
|
webEndpoints, endpointMediaTypes, getCorsConfiguration(), securityInterceptor,
|
|
|
|
endpointMediaTypes, getCorsConfiguration(), securityInterceptor, allEndpoints);
|
|
|
|
new EndpointLinksResolver(allEndpoints));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private CloudFoundrySecurityInterceptor getSecurityInterceptor(WebClient.Builder webClientBuilder,
|
|
|
|
private CloudFoundrySecurityInterceptor getSecurityInterceptor(WebClient.Builder webClientBuilder,
|
|
|
@ -153,25 +154,33 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
|
|
|
static class IgnoredPathsSecurityConfiguration {
|
|
|
|
static class IgnoredPathsSecurityConfiguration {
|
|
|
|
|
|
|
|
|
|
|
|
@Bean
|
|
|
|
@Bean
|
|
|
|
WebFilterChainPostProcessor webFilterChainPostProcessor() {
|
|
|
|
WebFilterChainPostProcessor webFilterChainPostProcessor(
|
|
|
|
return new WebFilterChainPostProcessor();
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
|
|
|
|
|
|
|
|
return new WebFilterChainPostProcessor(handlerMapping);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static class WebFilterChainPostProcessor implements BeanPostProcessor {
|
|
|
|
static class WebFilterChainPostProcessor implements BeanPostProcessor {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final PathMappedEndpoints pathMappedEndpoints;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WebFilterChainPostProcessor(CloudFoundryWebFluxEndpointHandlerMapping handlerMapping) {
|
|
|
|
|
|
|
|
this.pathMappedEndpoints = new PathMappedEndpoints(BASE_PATH, handlerMapping::getAllEndpoints);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
|
|
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
|
|
|
if (bean instanceof WebFilterChainProxy webFilterChainProxy) {
|
|
|
|
if (bean instanceof WebFilterChainProxy webFilterChainProxy) {
|
|
|
|
return postProcess(webFilterChainProxy);
|
|
|
|
return postProcess(webFilterChainProxy, this.pathMappedEndpoints);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return bean;
|
|
|
|
return bean;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private WebFilterChainProxy postProcess(WebFilterChainProxy existing) {
|
|
|
|
private WebFilterChainProxy postProcess(WebFilterChainProxy existing, PathMappedEndpoints pathMappedEndpoints) {
|
|
|
|
|
|
|
|
List<String> paths = getPaths(pathMappedEndpoints);
|
|
|
|
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
|
|
|
|
ServerWebExchangeMatcher cloudFoundryRequestMatcher = ServerWebExchangeMatchers
|
|
|
|
.pathMatchers("/cloudfoundryapplication/**");
|
|
|
|
.pathMatchers(paths.toArray(new String[] {}));
|
|
|
|
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
|
|
|
|
WebFilter noOpFilter = (exchange, chain) -> chain.filter(exchange);
|
|
|
|
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
|
|
|
|
MatcherSecurityWebFilterChain ignoredRequestFilterChain = new MatcherSecurityWebFilterChain(
|
|
|
|
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
|
|
|
|
cloudFoundryRequestMatcher, Collections.singletonList(noOpFilter));
|
|
|
@ -180,6 +189,14 @@ public class ReactiveCloudFoundryActuatorAutoConfiguration {
|
|
|
|
return new WebFilterChainProxy(ignoredRequestFilterChain, allRequestsFilterChain);
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|