Browse Source

Remove use of self-signed.badssl.com

Closes gh-43708
pull/44767/head
Moritz Halbritter 9 months ago
parent
commit
09b3461394
  1. 116
      spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java
  2. BIN
      spring-boot-project/spring-boot-actuator-autoconfigure/src/test/resources/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/test.jks

116
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/ReactiveCloudFoundryActuatorAutoConfigurationTests.java

@ -16,6 +16,7 @@
package org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive; package org.springframework.boot.actuate.autoconfigure.cloudfoundry.reactive;
import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@ -24,6 +25,8 @@ import java.util.Map;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import reactor.netty.http.HttpResources; import reactor.netty.http.HttpResources;
@ -52,13 +55,19 @@ import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration; import org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner; import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
import org.springframework.boot.testsupport.classpath.resources.WithResource; import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.boot.web.reactive.function.client.WebClientCustomizer; import org.springframework.boot.web.reactive.function.client.WebClientCustomizer;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange; import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;
@ -78,6 +87,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link ReactiveCloudFoundryActuatorAutoConfiguration}. * Tests for {@link ReactiveCloudFoundryActuatorAutoConfiguration}.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @author Moritz Halbritter
*/ */
class ReactiveCloudFoundryActuatorAutoConfigurationTests { class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@ -300,53 +310,63 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
} }
@Test @Test
void skipSslValidation() { @WithPackageResources("test.jks")
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) void skipSslValidation() throws IOException {
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails("JKS", null, "classpath:test.jks", "secret");
"vcap.application.cf_api:https://my-cloud-controller.com", SslBundle sslBundle = SslBundle.of(new JksSslStoreBundle(keyStoreDetails, keyStoreDetails));
"management.cloudfoundry.skip-ssl-validation:true") try (MockWebServer server = new MockWebServer()) {
.run((context) -> { server.useHttps(sslBundle.createSslContext().getSocketFactory(), false);
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); server.enqueue(new MockResponse().setResponseCode(204));
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); server.start();
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
"cloudFoundrySecurityService"); .withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, "webClient"); "vcap.application.cf_api:https://my-cloud-controller.com",
doesNotFailWithSslException(() -> webClient.get() "management.cloudfoundry.skip-ssl-validation:true")
.uri("https://self-signed.badssl.com/") .run((context) -> {
.retrieve() CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
.toBodilessEntity() Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
.block(Duration.ofSeconds(30))); Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
}); "cloudFoundrySecurityService");
} WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
"webClient");
private static void doesNotFailWithSslException(Runnable action) { ResponseEntity<Void> response = webClient.get()
try { .uri(server.url("/").uri())
action.run(); .retrieve()
} .toBodilessEntity()
catch (RuntimeException ex) { .block(Duration.ofSeconds(30));
assertThat(findCause(ex, SSLException.class)).isNull(); assertThat(response.getStatusCode()).isEqualTo(HttpStatusCode.valueOf(204));
});
} }
} }
@Test @Test
void sslValidationNotSkippedByDefault() { @WithPackageResources("test.jks")
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class)) void sslValidationNotSkippedByDefault() throws IOException {
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id", JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails("JKS", null, "classpath:test.jks", "secret");
"vcap.application.cf_api:https://my-cloud-controller.com") SslBundle sslBundle = SslBundle.of(new JksSslStoreBundle(keyStoreDetails, keyStoreDetails));
.run((context) -> { try (MockWebServer server = new MockWebServer()) {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context); server.useHttps(sslBundle.createSslContext().getSocketFactory(), false);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor"); server.enqueue(new MockResponse().setResponseCode(204));
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor, server.start();
"cloudFoundrySecurityService"); this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService, "webClient"); .withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
assertThatExceptionOfType(RuntimeException.class) "vcap.application.cf_api:https://my-cloud-controller.com")
.isThrownBy(() -> webClient.get() .run((context) -> {
.uri("https://self-signed.badssl.com/") CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
.retrieve() Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
.toBodilessEntity() Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
.block(Duration.ofSeconds(30))) "cloudFoundrySecurityService");
.withCauseInstanceOf(SSLException.class); WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
}); "webClient");
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> webClient.get()
.uri(server.url("/").uri())
.retrieve()
.toBodilessEntity()
.block(Duration.ofSeconds(30)))
.withCauseInstanceOf(SSLException.class);
});
}
} }
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) { private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) {
@ -365,16 +385,6 @@ class ReactiveCloudFoundryActuatorAutoConfigurationTests {
"No operation found with request path " + requestPath + " from " + endpoint.getOperations()); "No operation found with request path " + requestPath + " from " + endpoint.getOperations());
} }
private static <E extends Throwable> E findCause(Throwable failure, Class<E> type) {
while (failure != null) {
if (type.isInstance(failure)) {
return type.cast(failure);
}
failure = failure.getCause();
}
return null;
}
@Endpoint(id = "test") @Endpoint(id = "test")
static class TestEndpoint { static class TestEndpoint {

BIN
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/resources/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/test.jks

Binary file not shown.
Loading…
Cancel
Save