Repository: knox Updated Branches: refs/heads/v0.7.0 5f148ce08 -> 477be1971
KNOX-640 - Make Cookie Domain Configurable Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/477be197 Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/477be197 Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/477be197 Branch: refs/heads/v0.7.0 Commit: 477be197117827ed5964571bb3d47425d11c5184 Parents: 5f148ce Author: Larry McCay <[email protected]> Authored: Thu Dec 10 15:52:34 2015 -0500 Committer: Larry McCay <[email protected]> Committed: Thu Dec 10 15:53:41 2015 -0500 ---------------------------------------------------------------------- .../gateway/service/knoxsso/WebSSOResource.java | 34 +++++++++++++++----- .../service/knoxsso/WebSSOResourceTest.java | 34 ++++++++++++++++---- 2 files changed, 53 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/477be197/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java ---------------------------------------------------------------------- diff --git a/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java b/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java index a5e0cd9..6c9bcfc 100644 --- a/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java +++ b/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResource.java @@ -50,6 +50,7 @@ import static javax.ws.rs.core.MediaType.APPLICATION_XML; public class WebSSOResource { private static final String SSO_COOKIE_SECURE_ONLY_INIT_PARAM = "knoxsso.cookie.secure.only"; private static final String SSO_COOKIE_MAX_AGE_INIT_PARAM = "knoxsso.cookie.max.age"; + private static final String SSO_COOKIE_DOMAIN_SUFFIX_PARAM = "knoxsso.cookie.domain.suffix"; private static final String SSO_COOKIE_TOKEN_TTL_PARAM = "knoxsso.token.ttl"; private static final String SSO_COOKIE_TOKEN_WHITELIST_PARAM = "knoxsso.redirect.whitelist.regex"; private static final String ORIGINAL_URL_REQUEST_PARAM = "originalUrl"; @@ -63,6 +64,7 @@ public class WebSSOResource { private int maxAge = -1; private long tokenTTL = 30000l; private String whitelist = null; + private String domainSuffix = null; @Context private HttpServletRequest request; @@ -94,6 +96,8 @@ public class WebSSOResource { } } + domainSuffix = context.getInitParameter(SSO_COOKIE_DOMAIN_SUFFIX_PARAM); + whitelist = context.getInitParameter(SSO_COOKIE_TOKEN_WHITELIST_PARAM); if (whitelist == null) { // default to local/relative targets @@ -177,8 +181,10 @@ public class WebSSOResource { Cookie c = new Cookie(JWT_COOKIE_NAME, token.toString()); c.setPath("/"); try { - String domain = getDomainName(original); - c.setDomain(domain); + String domain = getDomainName(original, domainSuffix); + if (domain != null) { + c.setDomain(domain); + } c.setHttpOnly(true); if (secureOnly) { c.setSecure(true); @@ -202,19 +208,31 @@ public class WebSSOResource { response.addCookie(c); } - String getDomainName(String url) throws URISyntaxException { + String getDomainName(String url, String domainSuffix) throws URISyntaxException { URI uri = new URI(url); String domain = uri.getHost(); + + // if the hostname ends with the domainSuffix the use the domainSuffix as + // the cookie domain + if (domainSuffix != null && domain.endsWith(domainSuffix)) { + return (domainSuffix.startsWith(".")) ? domainSuffix : "." + domainSuffix; + } + // if accessing via ip address do not wildcard the cookie domain + // let's use the default domain if (Urls.isIp(domain)) { - return domain; + return null; } + + // if there are fewer than 2 dots than this is likely a + // specific host and we should use the default domain if (Urls.dotOccurrences(domain) < 2) { - if (!domain.startsWith(".")) { - domain = "." + domain; - } - return domain; + return null; } + + // assume any non-ip address with more than + // 3 dots will need the first element removed and + // all subdmains accepted int idx = domain.indexOf('.'); if (idx == -1) { idx = 0; http://git-wip-us.apache.org/repos/asf/knox/blob/477be197/gateway-service-knoxsso/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java ---------------------------------------------------------------------- diff --git a/gateway-service-knoxsso/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java b/gateway-service-knoxsso/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java index d0f4896..20c0566 100644 --- a/gateway-service-knoxsso/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java +++ b/gateway-service-knoxsso/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java @@ -25,18 +25,38 @@ import org.junit.Test; * */ public class WebSSOResourceTest { + /** + * Domain name creation follows the following algorithm: + * 1. if the incoming request hostname endsWith a configured domain suffix return the suffix - with prefixed dot + * 2. if the request hostname is an ip address return null for default domain + * 3. if the request hostname has less than 3 dots return null for default domain + * 4. if request hostname has more than two dots strip the first element and return the remainder as domain + * @throws Exception + */ @Test public void testDomainNameCreation() throws Exception { WebSSOResource resource = new WebSSOResource(); // determine parent domain and wildcard the cookie domain with a dot prefix - Assert.assertTrue(resource.getDomainName("http://www.local.com").equals(".local.com")); - Assert.assertTrue(resource.getDomainName("http://ljm.local.com").equals(".local.com")); - Assert.assertTrue(resource.getDomainName("http://local.home").equals(".local.home")); - Assert.assertTrue(resource.getDomainName("http://localhost").equals(".localhost")); // chrome may not allow this - Assert.assertTrue(resource.getDomainName("http://local.home.test.com").equals(".home.test.com")); - + Assert.assertTrue(resource.getDomainName("http://www.local.com", null).equals(".local.com")); + Assert.assertTrue(resource.getDomainName("http://ljm.local.com", null).equals(".local.com")); + + // test scenarios that will leverage the default cookie domain + Assert.assertEquals(resource.getDomainName("http://local.home", null), null); + Assert.assertEquals(resource.getDomainName("http://localhost", null), null); // chrome may not allow this + + Assert.assertTrue(resource.getDomainName("http://local.home.test.com", null).equals(".home.test.com")); + + // check the suffix config feature + Assert.assertTrue(resource.getDomainName("http://local.home.test.com", ".test.com").equals(".test.com")); + Assert.assertEquals(".novalocal", resource.getDomainName("http://34526yewt.novalocal", ".novalocal")); + + // make sure that even if the suffix doesn't start with a dot that the domain does + // if we are setting a domain suffix then we want a specific domain for SSO and that + // will require all hosts in the domain in order for it to work + Assert.assertEquals(".novalocal", resource.getDomainName("http://34526yewt.novalocal", "novalocal")); + // ip addresses can not be wildcarded - may be a completely different domain - Assert.assertTrue(resource.getDomainName("http://127.0.0.1").equals("127.0.0.1")); + Assert.assertEquals(resource.getDomainName("http://127.0.0.1", null), null); } @Test
