|
|
|
|
@ -27,6 +27,7 @@ import javax.net.ssl.SSLException;
@@ -27,6 +27,7 @@ import javax.net.ssl.SSLException;
|
|
|
|
|
|
|
|
|
|
import okhttp3.mockwebserver.MockResponse; |
|
|
|
|
import okhttp3.mockwebserver.MockWebServer; |
|
|
|
|
import org.assertj.core.api.InstanceOfAssertFactories; |
|
|
|
|
import org.junit.jupiter.api.AfterEach; |
|
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
|
import reactor.netty.http.HttpResources; |
|
|
|
|
@ -43,7 +44,6 @@ import org.springframework.boot.actuate.endpoint.ApiVersion;
@@ -43,7 +44,6 @@ import org.springframework.boot.actuate.endpoint.ApiVersion;
|
|
|
|
|
import org.springframework.boot.actuate.endpoint.EndpointId; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.annotation.Endpoint; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.EndpointMapping; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.WebOperation; |
|
|
|
|
import org.springframework.boot.actuate.endpoint.web.WebOperationRequestPredicate; |
|
|
|
|
@ -74,7 +74,6 @@ import org.springframework.security.core.userdetails.MapReactiveUserDetailsServi
@@ -74,7 +74,6 @@ import org.springframework.security.core.userdetails.MapReactiveUserDetailsServi
|
|
|
|
|
import org.springframework.security.core.userdetails.User; |
|
|
|
|
import org.springframework.security.web.server.SecurityWebFilterChain; |
|
|
|
|
import org.springframework.security.web.server.WebFilterChainProxy; |
|
|
|
|
import org.springframework.test.util.ReflectionTestUtils; |
|
|
|
|
import org.springframework.test.web.reactive.server.WebTestClient; |
|
|
|
|
import org.springframework.web.cors.CorsConfiguration; |
|
|
|
|
import org.springframework.web.reactive.function.client.WebClient; |
|
|
|
|
@ -121,16 +120,16 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -121,16 +120,16 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
"vcap.application.cf_api:https://my-cloud-controller.com") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); |
|
|
|
|
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping, |
|
|
|
|
"endpointMapping"); |
|
|
|
|
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication"); |
|
|
|
|
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils.getField(handlerMapping, |
|
|
|
|
"corsConfiguration"); |
|
|
|
|
assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); |
|
|
|
|
assertThat(corsConfiguration.getAllowedMethods()) |
|
|
|
|
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name())); |
|
|
|
|
assertThat(corsConfiguration.getAllowedHeaders()) |
|
|
|
|
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type")); |
|
|
|
|
assertThat(handlerMapping).extracting("endpointMapping.path").isEqualTo("/cloudfoundryapplication"); |
|
|
|
|
assertThat(handlerMapping) |
|
|
|
|
.extracting("corsConfiguration", InstanceOfAssertFactories.type(CorsConfiguration.class)) |
|
|
|
|
.satisfies((corsConfiguration) -> { |
|
|
|
|
assertThat(corsConfiguration.getAllowedOrigins()).contains("*"); |
|
|
|
|
assertThat(corsConfiguration.getAllowedMethods()) |
|
|
|
|
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name())); |
|
|
|
|
assertThat(corsConfiguration.getAllowedHeaders()) |
|
|
|
|
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type")); |
|
|
|
|
}); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -150,12 +149,8 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -150,12 +149,8 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
this.contextRunner |
|
|
|
|
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", |
|
|
|
|
"vcap.application.cf_api:https://my-cloud-controller.com") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); |
|
|
|
|
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); |
|
|
|
|
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId"); |
|
|
|
|
assertThat(applicationId).isEqualTo("my-app-id"); |
|
|
|
|
}); |
|
|
|
|
.run((context) -> assertThat(getHandlerMapping(context)).extracting("securityInterceptor.applicationId") |
|
|
|
|
.isEqualTo("my-app-id")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
@ -163,28 +158,18 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -163,28 +158,18 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
this.contextRunner |
|
|
|
|
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", |
|
|
|
|
"vcap.application.cf_api:https://my-cloud-controller.com") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); |
|
|
|
|
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); |
|
|
|
|
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, |
|
|
|
|
"cloudFoundrySecurityService"); |
|
|
|
|
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService, |
|
|
|
|
"cloudControllerUrl"); |
|
|
|
|
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com"); |
|
|
|
|
}); |
|
|
|
|
.run((context) -> assertThat(getHandlerMapping(context)) |
|
|
|
|
.extracting("securityInterceptor.cloudFoundrySecurityService.cloudControllerUrl") |
|
|
|
|
.isEqualTo("https://my-cloud-controller.com")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() { |
|
|
|
|
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean( |
|
|
|
|
"cloudFoundryWebFluxEndpointHandlerMapping", CloudFoundryWebFluxEndpointHandlerMapping.class); |
|
|
|
|
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); |
|
|
|
|
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor, |
|
|
|
|
"cloudFoundrySecurityService"); |
|
|
|
|
assertThat(interceptorSecurityService).isNull(); |
|
|
|
|
}); |
|
|
|
|
.run((context) -> assertThat(context.getBean("cloudFoundryWebFluxEndpointHandlerMapping", |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping.class)) |
|
|
|
|
.extracting("securityInterceptor.cloudFoundrySecurityService") |
|
|
|
|
.isNull()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
@ -194,30 +179,30 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -194,30 +179,30 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
.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 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(); |
|
|
|
|
assertThat(context.getBean(WebFilterChainProxy.class)) |
|
|
|
|
.extracting("filters", InstanceOfAssertFactories.list(SecurityWebFilterChain.class)) |
|
|
|
|
.satisfies((filters) -> { |
|
|
|
|
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) { |
|
|
|
|
private static Boolean getMatches(List<? extends SecurityWebFilterChain> filters, String urlTemplate) { |
|
|
|
|
return filters.get(0) |
|
|
|
|
.matches(MockServerWebExchange.from(MockServerHttpRequest.get(urlTemplate).build())) |
|
|
|
|
.block(Duration.ofSeconds(30)); |
|
|
|
|
@ -322,20 +307,17 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -322,20 +307,17 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", |
|
|
|
|
"vcap.application.cf_api:https://my-cloud-controller.com", |
|
|
|
|
"management.cloudfoundry.skip-ssl-validation:true") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); |
|
|
|
|
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); |
|
|
|
|
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, |
|
|
|
|
"cloudFoundrySecurityService"); |
|
|
|
|
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, |
|
|
|
|
"webClient"); |
|
|
|
|
ResponseEntity<Void> response = webClient.get() |
|
|
|
|
.uri(server.url("/").uri()) |
|
|
|
|
.retrieve() |
|
|
|
|
.toBodilessEntity() |
|
|
|
|
.block(Duration.ofSeconds(30)); |
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(204)); |
|
|
|
|
}); |
|
|
|
|
.run((context) -> assertThat(getHandlerMapping(context)) |
|
|
|
|
.extracting("securityInterceptor.cloudFoundrySecurityService.webClient", |
|
|
|
|
InstanceOfAssertFactories.type(WebClient.class)) |
|
|
|
|
.satisfies((webClient) -> { |
|
|
|
|
ResponseEntity<Void> response = webClient.get() |
|
|
|
|
.uri(server.url("/").uri()) |
|
|
|
|
.retrieve() |
|
|
|
|
.toBodilessEntity() |
|
|
|
|
.block(Duration.ofSeconds(30)); |
|
|
|
|
assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(204)); |
|
|
|
|
})); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -351,21 +333,16 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@@ -351,21 +333,16 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
|
|
|
|
|
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) |
|
|
|
|
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", |
|
|
|
|
"vcap.application.cf_api:https://my-cloud-controller.com") |
|
|
|
|
.run((context) -> { |
|
|
|
|
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); |
|
|
|
|
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); |
|
|
|
|
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, |
|
|
|
|
"cloudFoundrySecurityService"); |
|
|
|
|
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, |
|
|
|
|
"webClient"); |
|
|
|
|
assertThatExceptionOfType(RuntimeException.class) |
|
|
|
|
.run((context) -> assertThat(getHandlerMapping(context)) |
|
|
|
|
.extracting("securityInterceptor.cloudFoundrySecurityService.webClient", |
|
|
|
|
InstanceOfAssertFactories.type(WebClient.class)) |
|
|
|
|
.satisfies((webClient) -> assertThatExceptionOfType(RuntimeException.class) |
|
|
|
|
.isThrownBy(() -> webClient.get() |
|
|
|
|
.uri(server.url("/").uri()) |
|
|
|
|
.retrieve() |
|
|
|
|
.toBodilessEntity() |
|
|
|
|
.block(Duration.ofSeconds(30))) |
|
|
|
|
.withCauseInstanceOf(SSLException.class); |
|
|
|
|
}); |
|
|
|
|
.withCauseInstanceOf(SSLException.class))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|