From a1e24b5dc9b1ab138e584e9ef4faeec8f6cb6701 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Fri, 21 Apr 2017 16:40:57 +0200 Subject: [PATCH] SONAR-9155 Fix HTTPS proxy authentication --- .../server/util/OkHttpClientProviderTest.java | 7 +++++-- .../bootstrap/ScannerWsClientProvider.java | 2 +- .../ws/client/OkHttpClientBuilder.java | 17 ++++++++++++----- .../sonarqube/ws/client/HttpConnectorTest.java | 12 ++++++++++-- .../ws/client/OkHttpClientBuilderTest.java | 5 ++--- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/server/sonar-server/src/test/java/org/sonar/server/util/OkHttpClientProviderTest.java b/server/sonar-server/src/test/java/org/sonar/server/util/OkHttpClientProviderTest.java index a1775074c95..a0dd69f21fe 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/util/OkHttpClientProviderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/util/OkHttpClientProviderTest.java @@ -22,7 +22,9 @@ package org.sonar.server.util; import java.io.IOException; import java.util.Base64; import okhttp3.OkHttpClient; +import okhttp3.Protocol; import okhttp3.Request; +import okhttp3.Response; import okhttp3.mockwebserver.MockResponse; import okhttp3.mockwebserver.MockWebServer; import okhttp3.mockwebserver.RecordedRequest; @@ -65,9 +67,10 @@ public class OkHttpClientProviderTest { settings.setProperty("http.proxyPassword", "the-password"); OkHttpClient client = underTest.provide(settings, runtime); - RecordedRequest recordedRequest = call(client); + Response response = new Response.Builder().protocol(Protocol.HTTP_1_1).request(new Request.Builder().url("http://foo").build()).code(407).build(); + Request request = client.proxyAuthenticator().authenticate(null, response); - assertThat(recordedRequest.getHeader("Proxy-Authorization")).isEqualTo("Basic " + Base64.getEncoder().encodeToString("the-login:the-password".getBytes())); + assertThat(request.header("Proxy-Authorization")).isEqualTo("Basic " + Base64.getEncoder().encodeToString("the-login:the-password".getBytes())); } @Test diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java index 8b3c4cc830b..3ffd9275d39 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerWsClientProvider.java @@ -55,7 +55,7 @@ public class ScannerWsClientProvider extends ProviderAdapter { // OkHttp detect 'http.proxyHost' java property, but credentials should be filled final String proxyUser = System.getProperty("http.proxyUser", ""); - if (!System.getProperty("http.proxyHost", "").isEmpty() && !proxyUser.isEmpty()) { + if (!proxyUser.isEmpty()) { connectorBuilder.proxyCredentials(proxyUser, System.getProperty("http.proxyPassword")); } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java index 2f4ff65767e..77ad1552be4 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpClientBuilder.java @@ -21,6 +21,7 @@ package org.sonarqube.ws.client; import java.io.FileInputStream; import java.io.IOException; +import java.net.HttpURLConnection; import java.net.Proxy; import java.security.GeneralSecurityException; import java.security.KeyStore; @@ -156,7 +157,16 @@ public class OkHttpClientBuilder { if (readTimeoutMs >= 0) { builder.readTimeout(readTimeoutMs, TimeUnit.MILLISECONDS); } - builder.addInterceptor(this::completeHeaders); + builder.addNetworkInterceptor(this::addUserAgent); + if (proxyLogin != null) { + builder.proxyAuthenticator((route, response) -> { + if (HttpURLConnection.HTTP_PROXY_AUTH == response.code()) { + String credential = Credentials.basic(proxyLogin, nullToEmpty(proxyPassword)); + return response.request().newBuilder().header("Proxy-Authorization", credential).build(); + } + return null; + }); + } ConnectionSpec tls = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .allEnabledTlsVersions() @@ -172,14 +182,11 @@ public class OkHttpClientBuilder { return builder.build(); } - private Response completeHeaders(Interceptor.Chain chain) throws IOException { + private Response addUserAgent(Interceptor.Chain chain) throws IOException { Request.Builder newRequest = chain.request().newBuilder(); if (userAgent != null) { newRequest.header("User-Agent", userAgent); } - if (proxyLogin != null) { - newRequest.header("Proxy-Authorization", Credentials.basic(proxyLogin, nullToEmpty(proxyPassword))); - } return chain.proceed(newRequest.build()); } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java index a0a4ef98698..ba6e9d4dc43 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/HttpConnectorTest.java @@ -20,6 +20,8 @@ package org.sonarqube.ws.client; import java.io.File; +import java.net.InetSocketAddress; +import java.net.Proxy; import java.util.List; import javax.net.ssl.SSLSocketFactory; import okhttp3.ConnectionSpec; @@ -138,16 +140,22 @@ public class HttpConnectorTest { @Test public void use_proxy_authentication() throws Exception { - answerHelloWorld(); + MockWebServer proxy = new MockWebServer(); + proxy.start(); underTest = HttpConnector.newBuilder() .url(serverUrl) + .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxy.getHostName(), proxy.getPort()))) .proxyCredentials("theProxyLogin", "theProxyPassword") .build(); GetRequest request = new GetRequest("api/issues/search"); + proxy.enqueue(new MockResponse().setResponseCode(407)); + proxy.enqueue(new MockResponse().setBody("OK!")); underTest.call(request); - RecordedRequest recordedRequest = server.takeRequest(); + RecordedRequest recordedRequest = proxy.takeRequest(); + assertThat(recordedRequest.getHeader("Proxy-Authorization")).isNull(); + recordedRequest = proxy.takeRequest(); assertThat(recordedRequest.getHeader("Proxy-Authorization")).isEqualTo(basic("theProxyLogin", "theProxyPassword")); } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/OkHttpClientBuilderTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/OkHttpClientBuilderTest.java index e7282314581..60698db9ead 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/OkHttpClientBuilderTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/OkHttpClientBuilderTest.java @@ -19,6 +19,7 @@ */ package org.sonarqube.ws.client; +import javax.net.ssl.SSLSocketFactory; import okhttp3.OkHttpClient; import org.junit.Rule; import org.junit.Test; @@ -27,8 +28,6 @@ import org.junit.rules.ExpectedException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import javax.net.ssl.SSLSocketFactory; - public class OkHttpClientBuilderTest { @Rule @@ -41,7 +40,7 @@ public class OkHttpClientBuilderTest { OkHttpClient okHttpClient = underTest.build(); assertThat(okHttpClient.proxy()).isNull(); - assertThat(okHttpClient.interceptors()).hasSize(1); + assertThat(okHttpClient.networkInterceptors()).hasSize(1); assertThat(okHttpClient.sslSocketFactory()).isNotNull(); } -- 2.39.5