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 2015/11/26 20:08:29 UTC

knox git commit: KNOX-635 - Provide Whitelisting for Redirect Destinations for KnoxSSO

Repository: knox
Updated Branches:
  refs/heads/master 39aa06ee8 -> ddaf373fc


KNOX-635 - Provide Whitelisting for Redirect Destinations for KnoxSSO

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

Branch: refs/heads/master
Commit: ddaf373fc14e0ae10d6ead8660673681774d8320
Parents: 39aa06e
Author: Larry McCay <lm...@hortonworks.com>
Authored: Thu Nov 26 14:08:11 2015 -0500
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Thu Nov 26 14:08:11 2015 -0500

----------------------------------------------------------------------
 gateway-service-knoxsso/pom.xml                 |  4 ++
 .../service/knoxsso/KnoxSSOMessages.java        |  4 ++
 .../gateway/service/knoxsso/WebSSOResource.java | 15 +++++++
 .../service/knoxsso/WebSSOResourceTest.java     | 33 +++++++++++++++
 .../apache/hadoop/gateway/util/RegExUtils.java  | 43 ++++++++++++++++++++
 5 files changed, 99 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/ddaf373f/gateway-service-knoxsso/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-service-knoxsso/pom.xml b/gateway-service-knoxsso/pom.xml
index b3c2d92..d608853 100644
--- a/gateway-service-knoxsso/pom.xml
+++ b/gateway-service-knoxsso/pom.xml
@@ -35,6 +35,10 @@
   <dependencies>
 	  <dependency>
 	    <groupId>${gateway-group}</groupId>
+	    <artifactId>gateway-util-common</artifactId>
+	  </dependency>
+	  <dependency>
+	    <groupId>${gateway-group}</groupId>
 	    <artifactId>gateway-spi</artifactId>
 	  </dependency>
 	  <dependency>

http://git-wip-us.apache.org/repos/asf/knox/blob/ddaf373f/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/KnoxSSOMessages.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/KnoxSSOMessages.java b/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/KnoxSSOMessages.java
index 598fb99..0c7ec87 100644
--- a/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/KnoxSSOMessages.java
+++ b/gateway-service-knoxsso/src/main/java/org/apache/hadoop/gateway/service/knoxsso/KnoxSSOMessages.java
@@ -59,4 +59,8 @@ public interface KnoxSSOMessages {
 
   @Message( level = MessageLevel.INFO, text = "The cookie max age is being set to: {0}.")
   void setMaxAge(String age);
+
+  @Message( level = MessageLevel.ERROR, text = "The original URL: {0} for redirecting back after authentication is " +
+  		"not valid according to the configured whitelist: {1}. See documentation for KnoxSSO Whitelisting.")
+  void whiteListMatchFail(String original, String whitelist);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/ddaf373f/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 4bab18c..f23bbbe 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
@@ -40,6 +40,7 @@ import org.apache.hadoop.gateway.services.GatewayServices;
 import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
 import org.apache.hadoop.gateway.services.security.token.TokenServiceException;
 import org.apache.hadoop.gateway.services.security.token.impl.JWT;
+import org.apache.hadoop.gateway.util.RegExUtils;
 import org.apache.hadoop.gateway.util.Urls;
 
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -50,6 +51,7 @@ 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_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";
   private static final String ORIGINAL_URL_COOKIE_NAME = "original-url";
   private static final String JWT_COOKIE_NAME = "hadoop-jwt";
@@ -58,6 +60,7 @@ public class WebSSOResource {
   private boolean secureOnly = true;
   private int maxAge = -1;
   private long tokenTTL = 30000l;
+  private String whitelist = null;
 
   @Context 
   private HttpServletRequest request;
@@ -89,6 +92,12 @@ public class WebSSOResource {
       }
     }
 
+    whitelist = context.getInitParameter(SSO_COOKIE_TOKEN_WHITELIST_PARAM);
+    if (whitelist == null) {
+      // default to local/relative targets
+      whitelist = "^/.*$";
+    }
+
     String ttl = context.getInitParameter(SSO_COOKIE_TOKEN_TTL_PARAM);
     if (ttl != null) {
       try {
@@ -126,6 +135,12 @@ public class WebSSOResource {
         log.originalURLNotFound();
         throw new WebApplicationException("Original URL not found in the request.", Response.Status.BAD_REQUEST);
       }
+      boolean validRedirect = RegExUtils.checkWhitelist(whitelist, original);
+      if (!validRedirect) {
+        log.whiteListMatchFail(original, whitelist);
+        throw new WebApplicationException("Original URL not valid according to the configured whitelist.",
+            Response.Status.BAD_REQUEST);
+      }
     }
 
     JWTokenAuthority ts = services.getService(GatewayServices.TOKEN_SERVICE);

http://git-wip-us.apache.org/repos/asf/knox/blob/ddaf373f/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 769e497..4d97f0b 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
@@ -17,6 +17,7 @@
  */
 package org.apache.hadoop.gateway.service.knoxsso;
 
+import org.apache.hadoop.gateway.util.RegExUtils;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -37,4 +38,36 @@ public class WebSSOResourceTest {
     // 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"));
   }
+
+  @Test
+  public void testWhitelistMatching() throws Exception {
+    String whitelist = "^https?://.*example.com:8080/.*$;" +
+        "^https?://.*example.com/.*$;" +
+        "^https?://.*example2.com:\\d{0,9}/.*$";
+
+    // match on explicit hostname/domain and port
+    Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example.com:8080/"));
+    // match on non-required port
+    Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example.com/"));
+    // match on required but any port
+    Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example2.com:1234/"));
+    // fail on missing port
+    Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example2.com/"));
+    // fail on invalid port
+    Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example.com:8081/"));
+    // fail on alphanumeric port
+    Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example.com:A080/"));
+    // fail on invalid hostname/domain
+    Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example.net:8080/"));
+    // fail on required port
+    Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist, 
+        "http://host.example2.com/"));
+  }
 }

http://git-wip-us.apache.org/repos/asf/knox/blob/ddaf373f/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/RegExUtils.java
----------------------------------------------------------------------
diff --git a/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/RegExUtils.java b/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/RegExUtils.java
new file mode 100644
index 0000000..0171a3e
--- /dev/null
+++ b/gateway-util-common/src/main/java/org/apache/hadoop/gateway/util/RegExUtils.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.gateway.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class RegExUtils {
+  /**
+   * Checks for a match of a given string against
+   * a whitelist of semi-colon separated regex patterns.
+   * @param whitelist - semi-colon separated patterns
+   * @param tomatch - the string to match against list
+   * @return true for a match otherwise false
+   */
+  public static boolean checkWhitelist(String whitelist, String tomatch) {
+    String[] patterns = whitelist.split(";");
+    for (String patternString : patterns) {
+      Pattern pattern = Pattern.compile(patternString);
+      Matcher matcher = pattern.matcher(tomatch);
+      if (matcher.matches()) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+}