فهرست منبع

svn merge -c 1587962 from trunk to branch-2 to fix:HDFS-6219. Proxy superuser configuration should use true client IP for address checks. Contributed by Daryn Sharp.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1587964 13f79535-47bb-0310-9956-ffa450edef68
Kihwal Lee 11 سال پیش
والد
کامیت
4a13429dce

+ 3 - 0
hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt

@@ -49,6 +49,9 @@ Release 2.5.0 - UNRELEASED
     HDFS-6194. Create new tests for ByteRangeInputStream.
     (Akira Ajisaka via wheat9)
 
+    HDFS-6219. Proxy superuser configuration should use true client IP for
+    address checks. (daryn via kihwal)
+
   OPTIMIZATIONS
 
     HDFS-6214. Webhdfs has poor throughput for files >2GB (daryn)

+ 18 - 1
hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java

@@ -25,6 +25,7 @@ import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.URL;
@@ -625,7 +626,7 @@ public class JspHelper {
       if (doAsUserFromQuery != null) {
         // create and attempt to authorize a proxy user
         ugi = UserGroupInformation.createProxyUser(doAsUserFromQuery, ugi);
-        ProxyUsers.authorize(ugi, request.getRemoteAddr(), conf);
+        ProxyUsers.authorize(ugi, getRemoteAddr(request), conf);
       }
     }
     
@@ -665,6 +666,22 @@ public class JspHelper {
     return ugi;
   }
 
+  // honor the X-Forwarded-For header set by a configured set of trusted
+  // proxy servers.  allows audit logging and proxy user checks to work
+  // via an http proxy
+  static String getRemoteAddr(HttpServletRequest request) {
+    String remoteAddr = request.getRemoteAddr();
+    String proxyHeader = request.getHeader("X-Forwarded-For");
+    if (proxyHeader != null && ProxyUsers.isProxyServer(remoteAddr)) {
+      final String clientAddr = proxyHeader.split(",")[0].trim();
+      if (!clientAddr.isEmpty()) {
+        remoteAddr = clientAddr;
+      }
+    }
+    return remoteAddr;
+  }
+
+
   /**
    * Expected user name should be a short name.
    */

+ 52 - 1
hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java

@@ -27,7 +27,6 @@ import static org.mockito.Mockito.*;
 import java.io.IOException;
 import java.io.StringReader;
 import java.net.InetSocketAddress;
-import java.text.MessageFormat;
 import java.util.ArrayList;
 
 import javax.servlet.ServletContext;
@@ -63,6 +62,7 @@ import org.apache.hadoop.security.authorize.ProxyUsers;
 import org.apache.hadoop.security.token.Token;
 import org.apache.hadoop.security.token.TokenIdentifier;
 import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
@@ -76,6 +76,13 @@ public class TestJspHelper {
   private final Configuration conf = new HdfsConfiguration();
   private String jspWriterOutput = "";
 
+  // allow user with TGT to run tests
+  @BeforeClass
+  public static void setupKerb() {
+    System.setProperty("java.security.krb5.kdc", "");
+    System.setProperty("java.security.krb5.realm", "NONE");
+  }    
+
   public static class DummySecretManager extends
       AbstractDelegationTokenSecretManager<DelegationTokenIdentifier> {
 
@@ -600,5 +607,49 @@ public class TestJspHelper {
         50020, 50075, 50076, 50010);
     assertNotNull(JspHelper.Url.authority("http", dnWithEmptyIp));
   }
+ 
+  private static String clientAddr = "1.1.1.1";
+  private static String chainedClientAddr = clientAddr+", 2.2.2.2";
+  private static String proxyAddr = "3.3.3.3";
+  
+  @Test
+  public void testRemoteAddr() {
+    assertEquals(clientAddr, getRemoteAddr(clientAddr, null, false));
+  }
+  
+  @Test
+  public void testRemoteAddrWithUntrustedProxy() {
+    assertEquals(proxyAddr, getRemoteAddr(clientAddr, proxyAddr, false));
+  }
+
+  @Test
+  public void testRemoteAddrWithTrustedProxy() {
+    assertEquals(clientAddr, getRemoteAddr(clientAddr, proxyAddr, true));
+    assertEquals(clientAddr, getRemoteAddr(chainedClientAddr, proxyAddr, true));
+  }
+
+  @Test
+  public void testRemoteAddrWithTrustedProxyAndEmptyClient() {
+    assertEquals(proxyAddr, getRemoteAddr(null, proxyAddr, true));
+    assertEquals(proxyAddr, getRemoteAddr("", proxyAddr, true));
+  }
+
+  private String getRemoteAddr(String clientAddr, String proxyAddr, boolean trusted) {
+    HttpServletRequest req = mock(HttpServletRequest.class);
+    when(req.getRemoteAddr()).thenReturn("1.2.3.4");
+
+    Configuration conf = new Configuration();
+    if (proxyAddr == null) {
+      when(req.getRemoteAddr()).thenReturn(clientAddr);
+    } else {
+      when(req.getRemoteAddr()).thenReturn(proxyAddr);
+      when(req.getHeader("X-Forwarded-For")).thenReturn(clientAddr);
+      if (trusted) {
+        conf.set(ProxyUsers.CONF_HADOOP_PROXYSERVERS, proxyAddr);
+      }
+    }
+    ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
+    return JspHelper.getRemoteAddr(req);
+  }
 }