Repository: knox Updated Branches: refs/heads/master b2ec86f71 -> 35b65a267
KNOX-1373 - Default dispatch whitelist should consider X-Forwarded-Host header Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/35b65a26 Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/35b65a26 Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/35b65a26 Branch: refs/heads/master Commit: 35b65a26727245b75420551851f78d574a6d2c0b Parents: b2ec86f Author: Phil Zampino <[email protected]> Authored: Tue Jul 3 14:35:57 2018 -0400 Committer: Phil Zampino <[email protected]> Committed: Tue Jul 3 14:37:19 2018 -0400 ---------------------------------------------------------------------- .../knox/gateway/util/WhitelistUtils.java | 23 +++++++-- .../knox/gateway/util/WhitelistUtilsTest.java | 53 ++++++++++++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/35b65a26/gateway-spi/src/main/java/org/apache/knox/gateway/util/WhitelistUtils.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/util/WhitelistUtils.java b/gateway-spi/src/main/java/org/apache/knox/gateway/util/WhitelistUtils.java index 220e448..37df2f6 100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/util/WhitelistUtils.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/util/WhitelistUtils.java @@ -67,10 +67,25 @@ public class WhitelistUtils { private static String deriveDefaultDispatchWhitelist(HttpServletRequest request) { String defaultWhitelist = null; - try { - defaultWhitelist = deriveDomainBasedWhitelist(InetAddress.getLocalHost().getCanonicalHostName()); - } catch (UnknownHostException e) { - // + // Check first for the X-Forwarded-Host header, and use it to derive the domain-based whitelist + String requestedHost = request.getHeader("X-Forwarded-Host"); + if (requestedHost != null && !requestedHost.isEmpty()) { + // The value may include port information, which needs to be removed + int portIndex = requestedHost.indexOf(":"); + if (portIndex > 0) { + requestedHost = requestedHost.substring(0, portIndex); + } + defaultWhitelist = deriveDomainBasedWhitelist(requestedHost); + } + + // If the domain-based whitelist could not be derived from the X-Forwarded-Host header value, then use the + // localhost FQDN + if (defaultWhitelist == null) { + try { + defaultWhitelist = deriveDomainBasedWhitelist(InetAddress.getLocalHost().getCanonicalHostName()); + } catch (UnknownHostException e) { + // + } } // If the domain could not be determined, default to just the local/relative whitelist http://git-wip-us.apache.org/repos/asf/knox/blob/35b65a26/gateway-spi/src/test/java/org/apache/knox/gateway/util/WhitelistUtilsTest.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/test/java/org/apache/knox/gateway/util/WhitelistUtilsTest.java b/gateway-spi/src/test/java/org/apache/knox/gateway/util/WhitelistUtilsTest.java index 1824fe6..272a35d 100644 --- a/gateway-spi/src/test/java/org/apache/knox/gateway/util/WhitelistUtilsTest.java +++ b/gateway-spi/src/test/java/org/apache/knox/gateway/util/WhitelistUtilsTest.java @@ -79,9 +79,36 @@ public class WhitelistUtilsTest { } @Test + public void testDefaultDomainWhitelistWithXForwardedHost() throws Exception { + final String serviceRole = "TEST"; + + String whitelist = + doTestGetDispatchWhitelist(createMockGatewayConfig(Collections.singletonList(serviceRole), null), + "host0.test.org", + "lb.external.test.org", + serviceRole); + assertNotNull(whitelist); + assertTrue(whitelist.contains("\\.external\\.test\\.org")); + } + + @Test + public void testDefaultDomainWhitelistWithXForwardedHostAndPort() throws Exception { + final String serviceRole = "TEST"; + + String whitelist = + doTestGetDispatchWhitelist(createMockGatewayConfig(Collections.singletonList(serviceRole), null), + "host0.test.org", + "lb.external.test.org:9090", + serviceRole); + assertNotNull(whitelist); + assertTrue(whitelist.contains("\\.external\\.test\\.org")); + assertFalse(whitelist.contains("9090")); + } + + @Test public void testConfiguredWhitelist() throws Exception { final String serviceRole = "TEST"; - final String WHITELIST = "^.*\\.my\\.domain\\.com.*$"; + final String WHITELIST = "^.*\\.my\\.domain\\.com.*$"; String whitelist = doTestGetDispatchWhitelist(createMockGatewayConfig(Collections.singletonList(serviceRole), WHITELIST), @@ -93,11 +120,11 @@ public class WhitelistUtilsTest { @Test public void testExplicitlyConfiguredDefaultWhitelist() throws Exception { final String serviceRole = "TEST"; - final String WHITELIST = "DEFAULT"; + final String WHITELIST = "DEFAULT"; String whitelist = doTestGetDispatchWhitelist(createMockGatewayConfig(Collections.singletonList(serviceRole), WHITELIST), - serviceRole); + serviceRole); assertNotNull(whitelist); assertTrue("Expected the derived localhost whitelist.", RegExUtils.checkWhitelist(whitelist, "http://localhost:9099/")); @@ -111,17 +138,27 @@ public class WhitelistUtilsTest { private String doTestGetDispatchWhitelist(GatewayConfig config, String serverName, String serviceRole) { + return doTestGetDispatchWhitelist(config, serverName, null, serviceRole); + } + + private String doTestGetDispatchWhitelist(GatewayConfig config, + String serverName, + String xForwardedHost, + String serviceRole) { ServletContext sc = EasyMock.createNiceMock(ServletContext.class); EasyMock.expect(sc.getAttribute("org.apache.knox.gateway.config")).andReturn(config).anyTimes(); EasyMock.replay(sc); HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); + if (xForwardedHost != null && !xForwardedHost.isEmpty()) { + EasyMock.expect(request.getHeader("X-Forwarded-Host")).andReturn(xForwardedHost).anyTimes(); + } EasyMock.expect(request.getAttribute("targetServiceRole")).andReturn(serviceRole).anyTimes(); EasyMock.expect(request.getServletContext()).andReturn(sc).anyTimes(); EasyMock.replay(request); String result = null; - if (serverName != null && !serverName.isEmpty() && !serverName.equalsIgnoreCase("localhost")) { + if (serverName != null && !serverName.isEmpty() && !serverName.equalsIgnoreCase("localhost") && xForwardedHost == null) { try { Method method = WhitelistUtils.class.getDeclaredMethod("deriveDomainBasedWhitelist", String.class); method.setAccessible(true); @@ -129,6 +166,14 @@ public class WhitelistUtilsTest { } catch (Exception e) { e.printStackTrace(); } + } else if (xForwardedHost != null && !xForwardedHost.isEmpty()) { + try { + Method method = WhitelistUtils.class.getDeclaredMethod("deriveDefaultDispatchWhitelist", HttpServletRequest.class); + method.setAccessible(true); + result = (String) method.invoke(null, request); + } catch (Exception e) { + e.printStackTrace(); + } } else { result = WhitelistUtils.getDispatchWhitelist(request); }
