package at.gv.egiz.eaaf.core.test.http; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetAddress; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Provider; import java.security.cert.X509Certificate; import org.apache.commons.lang3.RandomStringUtils; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.impl.client.CloseableHttpClient; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.impl.credential.EaafKeyStoreFactory; import at.gv.egiz.eaaf.core.impl.data.Pair; import at.gv.egiz.eaaf.core.impl.http.HttpClientConfiguration; import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; import okhttp3.HttpUrl; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; import okhttp3.tls.HandshakeCertificates; import okhttp3.tls.HeldCertificate; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/spring/test_eaaf_pvp_not_lazy.beans.xml") public class HttpClientFactoryTest { @Autowired private EaafKeyStoreFactory keyStoreFactory; @Autowired private IHttpClientFactory httpClientFactory; private MockWebServer mockWebServer = null; private HttpUrl mockServerUrl; /** * JUnit test set-up. * */ @Before public void setup() { } /** * jUnit test shutdown. * * @throws IOException In case of an mockWebServer error */ @After public void shutdown() throws IOException { if (mockWebServer != null) { mockWebServer.shutdown(); mockWebServer = null; } } @Test public void getDefaultClient() { final CloseableHttpClient client = httpClientFactory.getHttpClient(); Assert.assertNotNull("httpClient", client); } @Test public void getDefaultClientNoRedirect() { final CloseableHttpClient client = httpClientFactory.getHttpClient(false); Assert.assertNotNull("httpClient", client); } @Test public void getCustomClientsDefault() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); Assert.assertFalse("Wrong default config - Hostnamevalidation", config.isDisableHostnameValidation()); Assert.assertFalse("Wrong default config - TLS Server-certs", config.isDisableTlsHostCertificateValidation()); final CloseableHttpClient client1 = httpClientFactory.getHttpClient(config); Assert.assertNotNull("first http client", client1); final CloseableHttpClient client2 = httpClientFactory.getHttpClient(config); Assert.assertNotNull("second http client", client2); } @Test public void getCustomClientUnknownAuthMethod() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode(RandomStringUtils.randomAlphabetic(5)); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); } @Test public void getCustomClientBasicAuth() throws EaafException, ClientProtocolException, IOException, InterruptedException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("password"); config.setUsername("jUnit"); config.setPassword("password"); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); //setup test webserver that requestes http Basic authentication mockWebServer = new MockWebServer(); mockServerUrl = mockWebServer.url("/sp/junit"); mockWebServer.enqueue(new MockResponse() .setResponseCode(HttpURLConnection.HTTP_UNAUTHORIZED) .addHeader("www-authenticate: Basic realm=\"protected area\"") .setBody("Please authenticate.")); mockWebServer.enqueue(new MockResponse().setResponseCode(200) .setBody("Successful auth!")); //request webservice final HttpUriRequest httpGet2 = new HttpGet(mockServerUrl.url().toString()); final CloseableHttpResponse httpResp2 = client.execute(httpGet2); Assert.assertEquals("http statusCode", 200, httpResp2.getStatusLine().getStatusCode()); //check request contains basic authentication after authentication was requested final RecordedRequest httpReq1 = mockWebServer.takeRequest(); final RecordedRequest httpReq2 = mockWebServer.takeRequest(); Assert.assertNull("wrong BasicAuthHeader", httpReq1.getHeader("Authorization")); Assert.assertNotNull("missing BasicAuthHeader", httpReq2.getHeader("Authorization")); } @Test public void getCustomClientBasicAuthNoUsername() { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("password"); try { httpClientFactory.getHttpClient(config); Assert.fail("Wrong config not detected"); } catch (final EaafException e) { Assert.assertEquals("Wrong errorCode", "internal.httpclient.00", e.getErrorId()); } } @Test public void getCustomClientBasicAuthNoPassword() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("password"); config.setUsername(RandomStringUtils.randomAlphabetic(5)); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); } @Test public void getCustomClientX509AuthNoKeyStoreConfig() { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); try { httpClientFactory.getHttpClient(config); Assert.fail("Wrong config not detected"); } catch (final EaafException e) { Assert.assertEquals("Wrong errorCode", "internal.httpclient.01", e.getErrorId()); } } @Test public void getCustomClientX509AuthNoKeyPassword() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); config.buildKeyStoreConfig( "jks", "src/test/resources/data/junit.jks", "password", null); try { httpClientFactory.getHttpClient(config); Assert.fail("Wrong config not detected"); } catch (final EaafException e) { Assert.assertEquals("Wrong errorCode", "internal.httpclient.02", e.getErrorId()); } } @Test public void getCustomClientX509Auth() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); config.buildKeyStoreConfig( "jks", "src/test/resources/data/junit.jks", "password", null); config.setSslKeyPassword("password"); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); } @Test public void getCustomClientX509AuthWithAlias() throws EaafException, ClientProtocolException, IOException, KeyStoreException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); config.buildKeyStoreConfig( "jks", "src/test/resources/data/junit.jks", "password", null); config.setSslKeyPassword("password"); config.setSslKeyAlias("sig"); config.setDisableTlsHostCertificateValidation(true); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); //set-up mock-up web-server with SSL client authentication final Pair sslClientKeyStore = keyStoreFactory.buildNewKeyStore(config.getKeyStoreConfig()); final String localhost = InetAddress.getByName("localhost").getCanonicalHostName(); final HeldCertificate localhostCertificate = new HeldCertificate.Builder() .addSubjectAlternativeName(localhost) .build(); final HandshakeCertificates serverCertificates = new HandshakeCertificates.Builder() .addTrustedCertificate( (X509Certificate) sslClientKeyStore.getFirst().getCertificate(config.getSslKeyAlias())) .heldCertificate(localhostCertificate) .build(); mockWebServer = new MockWebServer(); mockWebServer.useHttps(serverCertificates.sslSocketFactory(), false); mockWebServer.requireClientAuth(); mockWebServer.enqueue(new MockResponse().setResponseCode(200) .setBody("Successful auth!")); mockServerUrl = mockWebServer.url("/sp/junit"); //perform test request final HttpUriRequest httpGet2 = new HttpGet(mockServerUrl.url().toString()); final CloseableHttpResponse httpResp2 = client.execute(httpGet2); Assert.assertEquals("http statusCode", 200, httpResp2.getStatusLine().getStatusCode()); } @Test public void getCustomClientX509AuthWrongKeyPassword() throws EaafException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); config.buildKeyStoreConfig( "jks", "src/test/resources/data/junit.jks", "password", null); config.setSslKeyPassword(RandomStringUtils.randomAlphanumeric(5)); config.setSslKeyAlias("sig"); try { httpClientFactory.getHttpClient(config); Assert.fail("Wrong key password not detected"); } catch (final EaafException e) { Assert.assertEquals("Wrong errorCode", "internal.httpclient.03", e.getErrorId()); } } @Test public void getCustomClientX509AuthWithWrongAlias() throws EaafException, KeyStoreException, ClientProtocolException, IOException { final HttpClientConfiguration config = new HttpClientConfiguration("jUnit"); config.setAuthMode("ssl"); config.buildKeyStoreConfig( "jks", "src/test/resources/data/junit.jks", "password", null); config.setSslKeyPassword("password"); config.setSslKeyAlias(RandomStringUtils.randomAlphabetic(5)); config.setDisableHostnameValidation(true); config.setFollowHttpRedirects(false); config.setDisableTlsHostCertificateValidation(true); final CloseableHttpClient client = httpClientFactory.getHttpClient(config); Assert.assertNotNull("httpClient", client); //set-up mock-up web-server with SSL client authentication final Pair sslClientKeyStore = keyStoreFactory.buildNewKeyStore(config.getKeyStoreConfig()); final String localhost = InetAddress.getByName("localhost").getCanonicalHostName(); final HeldCertificate localhostCertificate = new HeldCertificate.Builder() .addSubjectAlternativeName(localhost) .build(); final HandshakeCertificates serverCertificates = new HandshakeCertificates.Builder() .addTrustedCertificate( (X509Certificate) sslClientKeyStore.getFirst().getCertificate("meta")) .addTrustedCertificate( (X509Certificate) sslClientKeyStore.getFirst().getCertificate("sig")) .heldCertificate(localhostCertificate) .build(); mockWebServer = new MockWebServer(); mockWebServer.useHttps(serverCertificates.sslSocketFactory(), false); mockWebServer.requireClientAuth(); mockWebServer.enqueue(new MockResponse().setResponseCode(200) .setBody("Successful auth!")); mockServerUrl = mockWebServer.url("/sp/junit"); //perform test request final HttpUriRequest httpGet2 = new HttpGet(mockServerUrl.url().toString()); final CloseableHttpResponse httpResp2 = client.execute(httpGet2); Assert.assertEquals("http statusCode", 200, httpResp2.getStatusLine().getStatusCode()); } }