You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2017/05/10 18:31:07 UTC

knox git commit: KNOX-390 - extended to include proxy provided headers such as X-Forwarded-For

Repository: knox
Updated Branches:
  refs/heads/master 0f207409c -> c32cd10f2


KNOX-390 - extended to include proxy provided headers such as X-Forwarded-For

Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/c32cd10f
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/c32cd10f
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/c32cd10f

Branch: refs/heads/master
Commit: c32cd10f2cc10b053d2bda47a76bcbb51d2e802e
Parents: 0f20740
Author: Larry McCay <lm...@hortonworks.com>
Authored: Wed May 10 14:30:30 2017 -0400
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Wed May 10 14:31:02 2017 -0400

----------------------------------------------------------------------
 .../apache/hadoop/gateway/GatewayFilter.java    | 16 ++++++++++-
 .../gateway/config/impl/GatewayConfigImpl.java  |  7 +++++
 .../apache/hadoop/gateway/AuditLoggingTest.java | 21 +++++++++++++-
 .../hadoop/gateway/GatewayFilterTest.java       | 30 +++++++++++++++++++-
 .../hadoop/gateway/config/GatewayConfig.java    |  7 +++++
 .../hadoop/gateway/GatewayTestConfig.java       |  6 ++++
 .../hadoop/gateway/GatewayTestConfig.java       |  5 ++++
 7 files changed, 89 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayFilter.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayFilter.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayFilter.java
index da6ba61..ba12fd9 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayFilter.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayFilter.java
@@ -27,6 +27,7 @@ import org.apache.hadoop.gateway.audit.api.CorrelationContext;
 import org.apache.hadoop.gateway.audit.api.CorrelationServiceFactory;
 import org.apache.hadoop.gateway.audit.api.ResourceType;
 import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
+import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory;
@@ -126,7 +127,7 @@ public class GatewayFilter implements Filter {
     // Populate Audit/correlation parameters
     AuditContext auditContext = auditService.getContext();
     auditContext.setTargetServiceName( match == null ? null : match.getValue().getResourceRole() );
-    auditContext.setRemoteIp( servletRequest.getRemoteAddr() );
+    auditContext.setRemoteIp( getRemoteAddress(servletRequest) );
     auditContext.setRemoteHostname( servletRequest.getRemoteHost() );
     auditor.audit(
         Action.ACCESS, contextWithPathAndQuery, ResourceType.URI,
@@ -167,6 +168,19 @@ public class GatewayFilter implements Filter {
     //]
   }
 
+  private String getRemoteAddress(ServletRequest servletRequest) {
+    GatewayConfig gatewayConfig =
+        (GatewayConfig) servletRequest.getServletContext().
+        getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE);
+
+    String addrHeaderName = gatewayConfig.getHeaderNameForRemoteAddress();
+    String addr = ((HttpServletRequest)servletRequest).getHeader(addrHeaderName);
+    if (addr == null || addr.trim().isEmpty()) {
+      addr = servletRequest.getRemoteAddr();
+    }
+    return addr;
+  }
+
   @Override
   public void destroy() {
     for( Holder holder : holders ) {

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
index cd60cb4..3952d7b 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/config/impl/GatewayConfigImpl.java
@@ -137,6 +137,7 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
   public static final String GRAPHITE_METRICS_REPORTING_PORT = GATEWAY_CONFIG_FILE_PREFIX + ".graphite.metrics.reporting.port";
   public static final String GRAPHITE_METRICS_REPORTING_FREQUENCY = GATEWAY_CONFIG_FILE_PREFIX + ".graphite.metrics.reporting.frequency";
   public static final String GATEWAY_IDLE_TIMEOUT = GATEWAY_CONFIG_FILE_PREFIX + ".idle.timeout";
+  public static final String REMOTE_IP_HEADER_NAME = GATEWAY_CONFIG_FILE_PREFIX + ".remote.ip.header.name";
 
   /* @since 0.10 Websocket config variables */
   public static final String WEBSOCKET_FEATURE_ENABLED =  GATEWAY_CONFIG_FILE_PREFIX + ".websocket.feature.enabled";
@@ -817,4 +818,10 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig {
     return result;
   }
 
+  @Override
+  public String getHeaderNameForRemoteAddress() {
+    String value = getVar(REMOTE_IP_HEADER_NAME, "X-Forwarded-For");
+    return value;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-server/src/test/java/org/apache/hadoop/gateway/AuditLoggingTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/AuditLoggingTest.java b/gateway-server/src/test/java/org/apache/hadoop/gateway/AuditLoggingTest.java
index b4f5e39..a5893e6 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/AuditLoggingTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/AuditLoggingTest.java
@@ -33,6 +33,7 @@ import java.util.Iterator;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -46,6 +47,7 @@ import org.apache.hadoop.gateway.audit.api.ResourceType;
 import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
 import org.apache.hadoop.gateway.audit.log4j.audit.Log4jAuditService;
 import org.apache.hadoop.gateway.audit.log4j.correlation.Log4jCorrelationService;
+import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.dispatch.DefaultDispatch;
 import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory;
 import org.apache.hadoop.test.log.CollectAppender;
@@ -88,13 +90,21 @@ public class AuditLoggingTest {
     EasyMock.replay( config );
 
     HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+    ServletContext context = EasyMock.createNiceMock( ServletContext.class );
+    GatewayConfig gatewayConfig = EasyMock.createNiceMock( GatewayConfig.class );
     EasyMock.expect( request.getMethod() ).andReturn( METHOD ).anyTimes();
     EasyMock.expect( request.getPathInfo() ).andReturn( PATH ).anyTimes();
     EasyMock.expect( request.getContextPath() ).andReturn( CONTEXT_PATH ).anyTimes();
     EasyMock.expect( request.getRemoteAddr() ).andReturn( ADDRESS ).anyTimes();
     EasyMock.expect( request.getRemoteHost() ).andReturn( HOST ).anyTimes();
-
+    EasyMock.expect( request.getServletContext() ).andReturn( context ).anyTimes();
+    EasyMock.expect( context.getAttribute(
+        GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes();
+    EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn(
+        "Custom-Forwarded-For").anyTimes();
     EasyMock.replay( request );
+    EasyMock.replay( context );
+    EasyMock.replay( gatewayConfig );
 
     HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
     EasyMock.replay( response );
@@ -126,12 +136,21 @@ public class AuditLoggingTest {
     EasyMock.replay( config );
 
     HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+    ServletContext context = EasyMock.createNiceMock( ServletContext.class );
+    GatewayConfig gatewayConfig = EasyMock.createNiceMock( GatewayConfig.class );
     EasyMock.expect( request.getMethod() ).andReturn( METHOD ).anyTimes();
     EasyMock.expect( request.getPathInfo() ).andReturn( PATH ).anyTimes();
     EasyMock.expect( request.getContextPath() ).andReturn( CONTEXT_PATH ).anyTimes();
     EasyMock.expect( request.getRemoteAddr() ).andReturn( ADDRESS ).anyTimes();
     EasyMock.expect( request.getRemoteHost() ).andReturn( HOST ).anyTimes();
+    EasyMock.expect( request.getServletContext() ).andReturn( context ).anyTimes();
+    EasyMock.expect( context.getAttribute(
+        GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes();
+    EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn(
+        "Custom-Forwarded-For").anyTimes();
     EasyMock.replay( request );
+    EasyMock.replay( context );
+    EasyMock.replay( gatewayConfig );
 
     HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
     EasyMock.replay( response );

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-server/src/test/java/org/apache/hadoop/gateway/GatewayFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/test/java/org/apache/hadoop/gateway/GatewayFilterTest.java b/gateway-server/src/test/java/org/apache/hadoop/gateway/GatewayFilterTest.java
index 5c55929..4e1562c 100644
--- a/gateway-server/src/test/java/org/apache/hadoop/gateway/GatewayFilterTest.java
+++ b/gateway-server/src/test/java/org/apache/hadoop/gateway/GatewayFilterTest.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.gateway;
 
 import org.apache.hadoop.gateway.audit.api.AuditServiceFactory;
+import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
 import org.apache.hadoop.test.category.FastTests;
 import org.apache.hadoop.test.category.UnitTests;
@@ -59,9 +60,18 @@ public class GatewayFilterTest {
     EasyMock.replay( config );
 
     HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+    ServletContext context = EasyMock.createNiceMock( ServletContext.class );
+    GatewayConfig gatewayConfig = EasyMock.createNiceMock( GatewayConfig.class );
     EasyMock.expect( request.getPathInfo() ).andReturn( "source" ).anyTimes();
+    EasyMock.expect( request.getServletContext() ).andReturn( context ).anyTimes();
+    EasyMock.expect( context.getAttribute(
+        GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes();
+    EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn(
+        "Custom-Forwarded-For").anyTimes();
     EasyMock.replay( request );
-
+    EasyMock.replay( context );
+    EasyMock.replay( gatewayConfig );
+    
     HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
     EasyMock.replay( response );
 
@@ -81,8 +91,17 @@ public class GatewayFilterTest {
     EasyMock.replay( config );
 
     HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+    ServletContext context = EasyMock.createNiceMock( ServletContext.class );
+    GatewayConfig gatewayConfig = EasyMock.createNiceMock( GatewayConfig.class );
     EasyMock.expect( request.getPathInfo() ).andReturn( "source" ).anyTimes();
+    EasyMock.expect( request.getServletContext() ).andReturn( context ).anyTimes();
+    EasyMock.expect( context.getAttribute(
+        GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes();
+    EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn(
+        "Custom-Forwarded-For").anyTimes();
     EasyMock.replay( request );
+    EasyMock.replay( context );
+    EasyMock.replay( gatewayConfig );
 
     HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
     EasyMock.replay( response );
@@ -119,11 +138,20 @@ public class GatewayFilterTest {
     EasyMock.replay( config );
 
     HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+    ServletContext context = EasyMock.createNiceMock( ServletContext.class );
+    GatewayConfig gatewayConfig = EasyMock.createNiceMock( GatewayConfig.class );
     EasyMock.expect( request.getPathInfo() ).andReturn( "test-path/test-resource" ).anyTimes();
+    EasyMock.expect( request.getServletContext() ).andReturn( context ).anyTimes();
+    EasyMock.expect( context.getAttribute(
+        GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes();
+    EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn(
+        "Custom-Forwarded-For").anyTimes();
     request.setAttribute( AbstractGatewayFilter.TARGET_SERVICE_ROLE, "test-role" );
     EasyMock.expectLastCall().anyTimes();
     EasyMock.expect( request.getAttribute( AbstractGatewayFilter.TARGET_SERVICE_ROLE ) ).andReturn( "test-role" ).anyTimes();
     EasyMock.replay( request );
+    EasyMock.replay( context );
+    EasyMock.replay( gatewayConfig );
 
     HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
     EasyMock.replay( response );

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
index d49e2de..9d8e044 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/config/GatewayConfig.java
@@ -229,4 +229,11 @@ public interface GatewayConfig {
    */
   boolean isCookieScopingToPathEnabled();
 
+  /**
+   * Configured name of the HTTP Header that is expected
+   * to be set by a proxy in front of the gateway.
+   * @return
+   */
+  String getHeaderNameForRemoteAddress();
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java b/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index 41588b3..c079531 100644
--- a/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test-release-utils/src/main/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -472,4 +472,10 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig {
   public  boolean isCookieScopingToPathEnabled() {
       return false;
   }
+
+  @Override
+  public String getHeaderNameForRemoteAddress() {
+    return "X-Forwarded-For";
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/c32cd10f/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
index baf38e6..e96dde2 100644
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayTestConfig.java
@@ -530,4 +530,9 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig {
   public  boolean isCookieScopingToPathEnabled() {
       return false;
   }
+
+  @Override
+  public String getHeaderNameForRemoteAddress() {
+    return "X-Forwarded-For";
+  }
 }