You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by co...@apache.org on 2017/09/08 08:58:51 UTC
knox git commit: KNOX-1027 - Add support to configure the issuer for
the JWT filters
Repository: knox
Updated Branches:
refs/heads/master 5f413f35e -> ca9247f4d
KNOX-1027 - Add support to configure the issuer for the JWT filters
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/ca9247f4
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/ca9247f4
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/ca9247f4
Branch: refs/heads/master
Commit: ca9247f4d06eaeb8eb24b1696fd5a7b80cb13340
Parents: 5f413f3
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Thu Sep 7 10:14:20 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Fri Sep 8 09:58:27 2017 +0100
----------------------------------------------------------------------
.../jwt/filter/AbstractJWTFilter.java | 26 ++++++--
.../jwt/filter/JWTFederationFilter.java | 8 ++-
.../jwt/filter/SSOCookieFederationFilter.java | 6 +-
.../federation/AbstractJWTFilterTest.java | 66 +++++++++++++++++++-
4 files changed, 95 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/ca9247f4/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
index e938480..d4c6717 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AbstractJWTFilter.java
@@ -60,15 +60,24 @@ import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
*
*/
public abstract class AbstractJWTFilter implements Filter {
+ /**
+ * If specified, this configuration property refers to a value which the issuer of a received
+ * token must match. Otherwise, the default value "KNOXSSO" is used
+ */
+ public static final String JWT_EXPECTED_ISSUER = "jwt.expected.issuer";
+ public static final String JWT_DEFAULT_ISSUER = "KNOXSSO";
+
static JWTMessages log = MessagesFactory.get( JWTMessages.class );
- protected List<String> audiences;
- protected JWTokenAuthority authority;
- protected RSAPublicKey publicKey = null;
private static AuditService auditService = AuditServiceFactory.getAuditService();
private static Auditor auditor = auditService.getAuditor(
AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME,
AuditConstants.KNOX_COMPONENT_NAME );
+ protected List<String> audiences;
+ protected JWTokenAuthority authority;
+ protected RSAPublicKey publicKey = null;
+ private String expectedIssuer;
+
public abstract void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
@@ -90,6 +99,13 @@ public abstract class AbstractJWTFilter implements Filter {
}
}
+ protected void configureExpectedIssuer(FilterConfig filterConfig) {
+ expectedIssuer = filterConfig.getInitParameter(JWT_EXPECTED_ISSUER);;
+ if (expectedIssuer == null) {
+ expectedIssuer = JWT_DEFAULT_ISSUER;
+ }
+ }
+
/**
* @param expectedAudiences
* @return
@@ -222,8 +238,8 @@ public abstract class AbstractJWTFilter implements Filter {
}
if (verified) {
- // confirm that issue matches intended target - which for this filter must be KNOXSSO
- if (token.getIssuer().equals("KNOXSSO")) {
+ // confirm that issue matches intended target
+ if (expectedIssuer.equals(token.getIssuer())) {
// if there is no expiration data then the lifecycle is tied entirely to
// the cookie validity - otherwise ensure that the current time is before
// the designated expiration time
http://git-wip-us.apache.org/repos/asf/knox/blob/ca9247f4/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
index 2cbccf6..401e449 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
@@ -62,12 +62,14 @@ public class JWTFederationFilter extends AbstractJWTFilter {
if (verificationPEM != null) {
publicKey = CertificateUtils.parseRSAPublicKey(verificationPEM);
}
+
+ configureExpectedIssuer(filterConfig);
}
public void destroy() {
}
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String header = ((HttpServletRequest) request).getHeader("Authorization");
String wireToken = null;
@@ -79,7 +81,7 @@ public class JWTFederationFilter extends AbstractJWTFilter {
// check for query param
wireToken = ((HttpServletRequest) request).getParameter(paramName);
}
-
+
if (wireToken != null) {
try {
JWTToken token = new JWTToken(wireToken);
@@ -100,7 +102,7 @@ public class JWTFederationFilter extends AbstractJWTFilter {
protected void handleValidationError(HttpServletRequest request, HttpServletResponse response, int status,
String error) throws IOException {
if (error != null) {
- response.sendError(status, error);
+ response.sendError(status, error);
}
else {
response.sendError(status);
http://git-wip-us.apache.org/repos/asf/knox/blob/ca9247f4/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
index 2e37c76..cf14863 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/SSOCookieFederationFilter.java
@@ -51,7 +51,7 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter {
@Override
public void init( FilterConfig filterConfig ) throws ServletException {
super.init(filterConfig);
-
+
// configured cookieName
cookieName = filterConfig.getInitParameter(SSO_COOKIE_NAME);
if (cookieName == null) {
@@ -77,13 +77,15 @@ public class SSOCookieFederationFilter extends AbstractJWTFilter {
if (verificationPEM != null) {
publicKey = CertificateUtils.parseRSAPublicKey(verificationPEM);
}
+
+ configureExpectedIssuer(filterConfig);
}
public void destroy() {
}
@Override
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
String wireToken = null;
HttpServletRequest req = (HttpServletRequest) request;
http://git-wip-us.apache.org/repos/asf/knox/blob/ca9247f4/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/AbstractJWTFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/AbstractJWTFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/AbstractJWTFilterTest.java
index 1893647..6f221a9 100644
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/AbstractJWTFilterTest.java
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/AbstractJWTFilterTest.java
@@ -400,6 +400,65 @@ public abstract class AbstractJWTFilterTest {
}
}
+ @Test
+ public void testInvalidIssuer() throws Exception {
+ try {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("new-issuer", "alice", new Date(new Date().getTime() + 5000), privateKey);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be true.", !chain.doFilterCalled);
+ Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testValidIssuerViaConfig() throws Exception {
+ try {
+ Properties props = getProperties();
+ props.setProperty(AbstractJWTFilter.JWT_EXPECTED_ISSUER, "new-issuer");
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("new-issuer", "alice", new Date(new Date().getTime() + 5000), privateKey);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
protected Properties getProperties() {
Properties props = new Properties();
props.setProperty(
@@ -410,11 +469,16 @@ public abstract class AbstractJWTFilterTest {
protected SignedJWT getJWT(String sub, Date expires, RSAPrivateKey privateKey,
Properties props) throws Exception {
+ return getJWT(AbstractJWTFilter.JWT_DEFAULT_ISSUER, sub, expires, privateKey);
+ }
+
+ protected SignedJWT getJWT(String issuer, String sub, Date expires, RSAPrivateKey privateKey)
+ throws Exception {
List<String> aud = new ArrayList<String>();
aud.add("bar");
JWTClaimsSet claims = new JWTClaimsSet.Builder()
- .issuer("KNOXSSO")
+ .issuer(issuer)
.subject(sub)
.audience(aud)
.expirationTime(expires)