Skip to content

Commit

Permalink
Merge pull request #51 from cuioss/feature/fix-cuirestclient-hostname…
Browse files Browse the repository at this point in the history
…-test-cert

Fix certificate for hostname test by adding 127.0.0.1 as subjectAlter…
  • Loading branch information
cuioss committed Jul 29, 2024
2 parents 90a319c + ae7b999 commit 5c05c68
Showing 1 changed file with 82 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
*/
package de.cuioss.portal.restclient;

import de.cuioss.portal.configuration.PortalConfigurationSource;
import de.cuioss.portal.configuration.connections.impl.AuthenticationType;
import de.cuioss.portal.configuration.connections.impl.ConnectionMetadata;
import de.cuioss.portal.configuration.connections.impl.StaticTokenResolver;
import de.cuioss.portal.core.test.junit5.EnablePortalConfiguration;
import de.cuioss.portal.core.test.junit5.mockwebserver.EnableMockWebServer;
import de.cuioss.portal.core.test.junit5.mockwebserver.MockWebServerHolder;
import de.cuioss.portal.core.test.mocks.configuration.PortalTestConfiguration;
import de.cuioss.test.generator.Generators;
import de.cuioss.test.generator.TypedGenerator;
import de.cuioss.test.generator.impl.URLGenerator;
Expand All @@ -31,17 +29,21 @@
import de.cuioss.test.juli.junit5.EnableTestLogger;
import de.cuioss.tools.logging.CuiLogger;
import de.cuioss.uimodel.application.LoginCredentials;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.*;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.InternalServerErrorException;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import lombok.Setter;
import mockwebserver3.Dispatcher;
import mockwebserver3.MockResponse;
import mockwebserver3.MockWebServer;
import mockwebserver3.RecordedRequest;
import okhttp3.Headers;
import okhttp3.tls.HandshakeCertificates;
import okhttp3.tls.HeldCertificate;
import org.eclipse.microprofile.rest.client.ext.QueryParamStyle;
Expand All @@ -63,12 +65,18 @@
import java.util.concurrent.TimeUnit;

import static de.cuioss.portal.configuration.TracingConfigKeys.PORTAL_TRACING_ENABLED;
import static de.cuioss.portal.configuration.TracingConfigKeys.PORTAL_TRACING_REPORTER_URL;
import static de.cuioss.test.generator.Generators.enumValues;
import static de.cuioss.test.generator.Generators.letterStrings;
import static de.cuioss.test.juli.LogAsserts.assertLogMessagePresentContaining;
import static de.cuioss.tools.collect.CollectionLiterals.immutableMap;
import static okhttp3.tls.internal.TlsUtil.localhost;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

@EnableAutoWeld
@EnablePortalConfiguration(configuration = PORTAL_TRACING_ENABLED + ":true")
Expand Down Expand Up @@ -107,10 +115,6 @@ public interface TestResource extends Closeable {
Response getResponse();
}

@Inject
@PortalConfigurationSource
private PortalTestConfiguration configuration;

@Setter
private MockWebServer mockWebServer;

Expand Down Expand Up @@ -166,41 +170,46 @@ void closeServiceResource() {

@Test
void testError() {
final var underTest = new CuiRestClientBuilder(LOG).url(mockWebServer.url("error").toString()).basicAuth("user",
"pass");
final var underTest = new CuiRestClientBuilder(LOG)
.url(mockWebServer.url("error").toString())
.basicAuth("user", "pass");
service = underTest.build(TestResource.class);

assertThrows(WebApplicationException.class, service::test);

LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "-- Client request info --");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO,
assertLogMessagePresentContaining(TestLogLevel.INFO, "-- Client request info --");
assertLogMessagePresentContaining(TestLogLevel.INFO,
"Request URI: " + mockWebServer.url("error/test"));
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Method: GET");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Headers:");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Accept: [application/fhir+xml]");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Authorization: [Basic dXNlcjpwYXNz]");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Method: GET");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Headers:");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Accept: [application/fhir+xml]");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Authorization: [Basic dXNlcjpwYXNz]");
}

@Test
void testResponseError() {
service = new CuiRestClientBuilder(LOG).url(mockWebServer.url("error").toString()).build(TestResource.class);
service = new CuiRestClientBuilder(LOG)
.url(mockWebServer.url("error").toString())
.build(TestResource.class);

assertDoesNotThrow(service::getResponse);
}

@Test
void requestWithBody() {
service = new CuiRestClientBuilder(LOG).url(mockWebServer.url("").toString()).build(TestResource.class);
service = new CuiRestClientBuilder(LOG)
.url(mockWebServer.url("").toString())
.build(TestResource.class);
assertDoesNotThrow(() -> service.postString(STRING));

LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "-- Client request info --");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Request URI: " + mockWebServer.url("/post"));
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Method: POST");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Headers:");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Accept: [application/json]");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Content-Type: [text/plain]");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, "Body:");
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.INFO, STRING);

assertLogMessagePresentContaining(TestLogLevel.INFO, "-- Client request info --");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Request URI: " + mockWebServer.url("/post"));
assertLogMessagePresentContaining(TestLogLevel.INFO, "Method: POST");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Headers:");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Accept: [application/json]");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Content-Type: [text/plain]");
assertLogMessagePresentContaining(TestLogLevel.INFO, "Body:");
assertLogMessagePresentContaining(TestLogLevel.INFO, STRING);
}

@Test
Expand All @@ -209,7 +218,7 @@ void shouldLogHappyCase() {
var response = service.getResponse();
assertNotNull(response);
CuiRestClientBuilder.debugResponse(response, LOG);
LogAsserts.assertLogMessagePresentContaining(TestLogLevel.DEBUG, "-- Client response filter --");
assertLogMessagePresentContaining(TestLogLevel.DEBUG, "-- Client response filter --");
}

@Test
Expand All @@ -227,11 +236,12 @@ void shouldDeactivateLogTracing() {

@Test
void testCorrectHostname() {
final var handshakeCertificates = localhost();
final var handshakeCertificates = localhostCerts();
mockWebServer.useHttps(handshakeCertificates.sslSocketFactory());

service = new CuiRestClientBuilder(LOG).sslContext(handshakeCertificates.sslContext())
.url(mockWebServer.url("success").toString()).build(TestResource.class);
service = new CuiRestClientBuilder(LOG)
.sslContext(handshakeCertificates.sslContext())
.url(mockWebServer.url("success").toString())
.build(TestResource.class);

final var result = service.test();

Expand Down Expand Up @@ -293,13 +303,17 @@ void registersExceptionMapper() {
assertThrows(ExceptionMapperTestException.class, serviceError::test);
}


@Test
void basicAuth() {
service = new CuiRestClientBuilder(LOG)
.connectionMetadata(ConnectionMetadata.builder().serviceUrl(mockWebServer.url("success").toString())
.connectionMetadata(ConnectionMetadata.builder()
.serviceUrl(mockWebServer.url("success").toString())
.authenticationType(AuthenticationType.BASIC)
.loginCredentials(LoginCredentials.builder().username("user").password("pass").build()).build())
.loginCredentials(LoginCredentials.builder()
.username("user")
.password("pass")
.build())
.build())
.build(TestResource.class);

assertDoesNotThrow(() -> service.test());
Expand All @@ -310,7 +324,8 @@ void basicAuth() {
@Test
void sendAuthenticationToken() {
service = new CuiRestClientBuilder(LOG)
.connectionMetadata(ConnectionMetadata.builder().serviceUrl(mockWebServer.url("success").toString())
.connectionMetadata(ConnectionMetadata.builder()
.serviceUrl(mockWebServer.url("success").toString())
.authenticationType(AuthenticationType.TOKEN_APPLICATION)
.tokenResolver(new StaticTokenResolver("Authentication", "BEARER abc")).build())
.build(TestResource.class);
Expand All @@ -323,7 +338,8 @@ void sendAuthenticationToken() {
@Test
void shouldHandleAllAttributes() {
var builder = new CuiRestClientBuilder(LOG)
.connectionMetadata(ConnectionMetadata.builder().serviceUrl(mockWebServer.url("success").toString())
.connectionMetadata(ConnectionMetadata.builder()
.serviceUrl(mockWebServer.url("success").toString())
.authenticationType(AuthenticationType.NONE).connectionTimeout(4).proxyHost("host")
.proxyPort(8080).disableHostNameVerification(true).contextMap(immutableMap("key", "value"))
.connectionTimeoutUnit(TimeUnit.MICROSECONDS).readTimeout(7).build());
Expand All @@ -334,7 +350,8 @@ void shouldHandleAllAttributes() {
@Test
void sendGeneralToken() {
CuiRestClientBuilder cuiRestClientBuilder = new CuiRestClientBuilder(LOG);
cuiRestClientBuilder.connectionMetadata(ConnectionMetadata.builder().serviceUrl(mockWebServer.url("success").toString())
cuiRestClientBuilder.connectionMetadata(ConnectionMetadata.builder()
.serviceUrl(mockWebServer.url("success").toString())
.authenticationType(AuthenticationType.TOKEN_APPLICATION)
.tokenResolver(new StaticTokenResolver("Key", "Value")).build());
service = cuiRestClientBuilder.build(TestResource.class);
Expand All @@ -346,7 +363,9 @@ void sendGeneralToken() {

@Test
void canEnableDefaultExceptionHandler() {
service = new CuiRestClientBuilder(LOG).url(mockWebServer.url("error").toString()).build(TestResource.class);
service = new CuiRestClientBuilder(LOG)
.url(mockWebServer.url("error").toString())
.build(TestResource.class);
assertThrows(InternalServerErrorException.class, () -> service.test());

service = new CuiRestClientBuilder(LOG).url(mockWebServer.url("error").toString())
Expand All @@ -369,7 +388,9 @@ void canEnableDefaultExceptionHandler() {
*/
@Test
void handlesCollections() {
service = new CuiRestClientBuilder(LOG).url(mockWebServer.url("").toString()).build(TestResource.class);
service = new CuiRestClientBuilder(LOG)
.url(mockWebServer.url("").toString())
.build(TestResource.class);
// RESTEASY003145: Unable to find a MessageBodyReader of content-type
// application/json
// and type interface java.util.List
Expand All @@ -391,7 +412,6 @@ void builderShouldHandleAdditionalAttributes() throws URISyntaxException {
assertDoesNotThrow(() -> builder.build(TestResource.class));
}


private RecordedRequest takeRequest() {
try {
return mockWebServer.takeRequest(25, TimeUnit.SECONDS);
Expand All @@ -409,4 +429,22 @@ private static class ExceptionMapperTestException extends RuntimeException {
ExceptionMapperTestException() {
}
}

/**
* @return same as #{okhttp3.tls.internal.TlsUtil#localhost()} but
* additionally with subjectAlternativeName {@code 127.0.0.1}.
*/
private HandshakeCertificates localhostCerts() {
// Generate a self-signed cert for the server to serve and the client to trust.
var heldCertificate = new HeldCertificate.Builder()
.commonName("localhost")
.addSubjectAlternativeName("localhost")
.addSubjectAlternativeName("127.0.01")
.addSubjectAlternativeName("localhost.localdomain")
.build();
return new HandshakeCertificates.Builder()
.heldCertificate(heldCertificate)
.addTrustedCertificate(heldCertificate.certificate())
.build();
}
}

0 comments on commit 5c05c68

Please sign in to comment.