]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7465 Support encryption of HTTP proxy properties
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 10 Mar 2016 22:14:01 +0000 (23:14 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 11 Mar 2016 12:50:29 +0000 (13:50 +0100)
Removing the calls to Settings.getProperties() as it keeps
encrypted properties values.

sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java
sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java

index 13e27f72a433f2c8b42e04c220f2db3a370735f4..69c2f14aa4aad0bbdb861d9a2af1c4f7fad77edb 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.core.util;
 
-
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
@@ -41,7 +40,6 @@ import java.net.URI;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
-import java.util.Map;
 import java.util.zip.GZIPInputStream;
 import javax.annotation.Nullable;
 import org.apache.commons.codec.binary.Base64;
@@ -52,6 +50,7 @@ import org.sonar.api.utils.HttpDownloader;
 import org.sonar.api.utils.SonarException;
 import org.sonar.api.utils.log.Loggers;
 
+import static org.apache.commons.lang.StringUtils.isNotEmpty;
 import static org.sonar.core.util.FileUtils.deleteQuietly;
 
 /**
@@ -60,6 +59,7 @@ import static org.sonar.core.util.FileUtils.deleteQuietly;
  * @since 2.2
  */
 public class DefaultHttpDownloader extends HttpDownloader {
+
   private final BaseHttpDownloader downloader;
   private final Integer readTimeout;
   private final Integer connectTimeout;
@@ -75,7 +75,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
   public DefaultHttpDownloader(Server server, Settings settings, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
     this.readTimeout = readTimeout;
     this.connectTimeout = connectTimeout;
-    downloader = new BaseHttpDownloader(settings.getProperties(), server.getVersion());
+    downloader = new BaseHttpDownloader(new ProxySystem(), settings, server.getVersion());
   }
 
   public DefaultHttpDownloader(Settings settings) {
@@ -89,7 +89,7 @@ public class DefaultHttpDownloader extends HttpDownloader {
   public DefaultHttpDownloader(Settings settings, @Nullable Integer connectTimeout, @Nullable Integer readTimeout) {
     this.readTimeout = readTimeout;
     this.connectTimeout = connectTimeout;
-    downloader = new BaseHttpDownloader(settings.getProperties(), null);
+    downloader = new BaseHttpDownloader(new ProxySystem(), settings, null);
   }
 
   @Override
@@ -157,7 +157,17 @@ public class DefaultHttpDownloader extends HttpDownloader {
     throw new SonarException(String.format("Fail to download: %s (%s)", uri, getProxySynthesis(uri)), e);
   }
 
-  public static class BaseHttpDownloader {
+  static class ProxySystem {
+    public void setProperty(String key, String value) {
+      System.setProperty(key, value);
+    }
+
+    public void setDefaultAuthenticator(Authenticator authenticator) {
+      Authenticator.setDefault(authenticator);
+    }
+  }
+
+  static class BaseHttpDownloader {
 
     private static final String GET = "GET";
     private static final String HTTP_PROXY_USER = "http.proxyUser";
@@ -169,15 +179,22 @@ public class DefaultHttpDownloader extends HttpDownloader {
 
     private String userAgent;
 
-    public BaseHttpDownloader(Map<String, String> settings, @Nullable String userAgent) {
-      initProxy(settings);
+    BaseHttpDownloader(ProxySystem system, Settings settings, @Nullable String userAgent) {
+      initProxy(system, settings);
       initUserAgent(userAgent);
     }
 
-    private void initProxy(Map<String, String> settings) {
-      propagateProxySystemProperties(settings);
-      if (requiresProxyAuthentication(settings)) {
-        registerProxyCredentials(settings);
+    private void initProxy(ProxySystem system, Settings settings) {
+      // propagate system properties
+      for (String key : PROXY_SETTINGS) {
+        if (settings.hasKey(key)) {
+          system.setProperty(key, settings.getString(key));
+        }
+      }
+      // register credentials
+      String login = settings.getString(HTTP_PROXY_USER);
+      if (isNotEmpty(login)) {
+        system.setDefaultAuthenticator(new ProxyAuthenticator(login, settings.getString(HTTP_PROXY_PASSWORD)));
       }
     }
 
@@ -207,24 +224,6 @@ public class DefaultHttpDownloader extends HttpDownloader {
       return Joiner.on(", ").join(descriptions);
     }
 
-    private static void registerProxyCredentials(Map<String, String> settings) {
-      Authenticator.setDefault(new ProxyAuthenticator(
-        settings.get(HTTP_PROXY_USER),
-        settings.get(HTTP_PROXY_PASSWORD)));
-    }
-
-    private boolean requiresProxyAuthentication(Map<String, String> settings) {
-      return settings.containsKey(HTTP_PROXY_USER);
-    }
-
-    private void propagateProxySystemProperties(Map<String, String> settings) {
-      for (String key : PROXY_SETTINGS) {
-        if (settings.containsKey(key)) {
-          System.setProperty(key, settings.get(key));
-        }
-      }
-    }
-
     public InputSupplier<InputStream> newInputSupplier(URI uri) {
       return newInputSupplier(uri, GET, null, null, null, null);
     }
@@ -357,18 +356,18 @@ public class DefaultHttpDownloader extends HttpDownloader {
         return resultingInputStream;
       }
     }
+  }
 
-    private static class ProxyAuthenticator extends Authenticator {
-      private final PasswordAuthentication auth;
+  static class ProxyAuthenticator extends Authenticator {
+    private final PasswordAuthentication auth;
 
-      ProxyAuthenticator(String user, String password) {
-        auth = new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
-      }
+    ProxyAuthenticator(String user, @Nullable String password) {
+      auth = new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
+    }
 
-      @Override
-      protected PasswordAuthentication getPasswordAuthentication() {
-        return auth;
-      }
+    @Override
+    protected PasswordAuthentication getPasswordAuthentication() {
+      return auth;
     }
   }
 
index 23aa73b4fc72cee7ec8214396866541696e3322a..d25429bbc7801a10bd27f7abc474ed41ee8c959e 100644 (file)
@@ -22,7 +22,9 @@ package org.sonar.core.util;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.Authenticator;
 import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
 import java.net.Proxy;
 import java.net.ProxySelector;
 import java.net.SocketAddress;
@@ -33,9 +35,9 @@ import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Properties;
 import java.util.zip.GZIPOutputStream;
-
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 import org.junit.Rule;
@@ -52,9 +54,13 @@ import org.simpleframework.transport.connect.SocketConnection;
 import org.sonar.api.config.Settings;
 import org.sonar.api.platform.Server;
 import org.sonar.api.utils.SonarException;
+
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 public class DefaultHttpDownloaderTest {
@@ -247,6 +253,46 @@ public class DefaultHttpDownloaderTest {
     String description = new DefaultHttpDownloader(new Settings()).description(new URI("http://sonarsource.org"));
     assertThat(description).matches("http://sonarsource.org \\(.*\\)");
   }
+
+  @Test
+  public void configure_http_proxy() {
+    DefaultHttpDownloader.ProxySystem system = mock(DefaultHttpDownloader.ProxySystem.class);
+    Settings settings = new Settings();
+    settings.setProperty("http.proxyHost", "1.2.3.4");
+    settings.setProperty("http.proxyPort", "80");
+
+    new DefaultHttpDownloader.BaseHttpDownloader(system, settings, null);
+
+    verify(system).setProperty("http.proxyHost", "1.2.3.4");
+    verify(system).setProperty("http.proxyPort", "80");
+    verify(system, never()).setDefaultAuthenticator(any(Authenticator.class));
+  }
+
+  @Test
+  public void configure_http_proxy_credentials() {
+    DefaultHttpDownloader.ProxySystem system = mock(DefaultHttpDownloader.ProxySystem.class);
+    Settings settings = new Settings();
+    settings.setProperty("https.proxyHost", "1.2.3.4");
+    settings.setProperty("http.proxyUser", "the_login");
+    settings.setProperty("http.proxyPassword", "the_passwd");
+
+    new DefaultHttpDownloader.BaseHttpDownloader(system, settings, null);
+
+    verify(system).setDefaultAuthenticator(argThat(new TypeSafeMatcher<Authenticator>() {
+      @Override
+      protected boolean matchesSafely(Authenticator authenticator) {
+        DefaultHttpDownloader.ProxyAuthenticator a = (DefaultHttpDownloader.ProxyAuthenticator) authenticator;
+        PasswordAuthentication authentication = a.getPasswordAuthentication();
+        return authentication.getUserName().equals("the_login") &&
+          new String(authentication.getPassword()).equals("the_passwd");
+      }
+
+      @Override
+      public void describeTo(Description description) {
+      }
+    }));
+  }
+
 }
 
 class FakeProxy extends Proxy {