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 <[email protected]> Authored: Wed May 10 14:30:30 2017 -0400 Committer: Larry McCay <[email protected]> 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"; + } }
