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;
+ }
+
+}