You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/09/20 14:36:28 UTC
[04/12] knox git commit: KNOX-1047 - Add some tests for the Knox
Token Service
KNOX-1047 - Add some tests for the Knox Token Service
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/3557612d
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/3557612d
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/3557612d
Branch: refs/heads/KNOX-998-Package_Restructuring
Commit: 3557612d5a5d904c3dfa61ba03cccfbbd365b296
Parents: 4978951
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Sep 19 12:17:59 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Sep 19 12:17:59 2017 +0100
----------------------------------------------------------------------
.../federation/AbstractJWTFilterTest.java | 14 +-
.../federation/JWTFederationFilterTest.java | 1 -
.../federation/SSOCookieProviderTest.java | 1 -
gateway-service-knoxtoken/pom.xml | 29 ++-
.../service/knoxtoken/TokenResource.java | 31 +--
.../knoxtoken/TokenServiceResourceTest.java | 256 ++++++++++++++++++-
6 files changed, 293 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/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 6f221a9..d477f1f 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
@@ -60,7 +60,7 @@ import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Assert;
-import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
import com.nimbusds.jose.*;
@@ -74,16 +74,16 @@ public abstract class AbstractJWTFilterTest {
private static final String dnTemplate = "CN={0},OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
protected AbstractJWTFilter handler = null;
- protected RSAPublicKey publicKey = null;
- protected RSAPrivateKey privateKey = null;
- protected String pem = null;
+ protected static RSAPublicKey publicKey = null;
+ protected static RSAPrivateKey privateKey = null;
+ protected static String pem = null;
protected abstract void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
protected abstract void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
protected abstract String getAudienceProperty();
protected abstract String getVerificationPemProperty();
- private String buildDistinguishedName(String hostname) {
+ private static String buildDistinguishedName(String hostname) {
MessageFormat headerFormatter = new MessageFormat(dnTemplate);
String[] paramArray = new String[1];
paramArray[0] = hostname;
@@ -91,8 +91,8 @@ public abstract class AbstractJWTFilterTest {
return dn;
}
- @Before
- public void setup() throws Exception, NoSuchAlgorithmException {
+ @BeforeClass
+ public static void generateKeys() throws Exception, NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair KPair = kpg.generateKeyPair();
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTFederationFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTFederationFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTFederationFilterTest.java
index d19d999..99a3780 100644
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTFederationFilterTest.java
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTFederationFilterTest.java
@@ -32,7 +32,6 @@ public class JWTFederationFilterTest extends AbstractJWTFilterTest {
@Before
public void setup() throws Exception, NoSuchAlgorithmException {
- super.setup();
handler = new TestJWTFederationFilter();
((TestJWTFederationFilter) handler).setTokenService(new TestJWTokenAuthority(publicKey));
}
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
index 85f7d59..768755b 100644
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
@@ -45,7 +45,6 @@ public class SSOCookieProviderTest extends AbstractJWTFilterTest {
@Before
public void setup() throws Exception, NoSuchAlgorithmException {
- super.setup();
handler = new TestSSOCookieFederationProvider();
((TestSSOCookieFederationProvider) handler).setTokenService(new TestJWTokenAuthority(publicKey));
}
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/gateway-service-knoxtoken/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/pom.xml b/gateway-service-knoxtoken/pom.xml
index 1dafa20..e27b7b0 100644
--- a/gateway-service-knoxtoken/pom.xml
+++ b/gateway-service-knoxtoken/pom.xml
@@ -56,19 +56,20 @@
<groupId>${gateway-group}</groupId>
<artifactId>gateway-provider-jersey</artifactId>
</dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.knox</groupId>
- <artifactId>gateway-test-utils</artifactId>
- <scope>test</scope>
- </dependency>
<dependency>
- <groupId>org.easymock</groupId>
- <artifactId>easymock</artifactId>
- <scope>test</scope>
- </dependency> </dependencies>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
index 4fda69f..43dd526 100644
--- a/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
@@ -22,6 +22,8 @@ import java.security.Principal;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
+import java.util.List;
+
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -55,15 +57,15 @@ public class TokenResource {
static final String RESOURCE_PATH = "knoxtoken/api/v1/token";
private static TokenServiceMessages log = MessagesFactory.get( TokenServiceMessages.class );
private long tokenTTL = 30000l;
- private String[] targetAudiences = null;
+ private List<String> targetAudiences = new ArrayList<>();
private String tokenTargetUrl = null;
private Map<String,Object> tokenClientDataMap = null;
@Context
- private HttpServletRequest request;
+ HttpServletRequest request;
@Context
- private HttpServletResponse response;
+ HttpServletResponse response;
@Context
ServletContext context;
@@ -73,7 +75,10 @@ public class TokenResource {
String audiences = context.getInitParameter(TOKEN_AUDIENCES_PARAM);
if (audiences != null) {
- targetAudiences = audiences.split(",");
+ String[] auds = audiences.split(",");
+ for (int i = 0; i < auds.length; i++) {
+ targetAudiences.add(auds[i]);
+ }
}
String ttl = context.getInitParameter(TOKEN_TTL_PARAM);
@@ -85,7 +90,7 @@ public class TokenResource {
log.invalidTokenTTLEncountered(ttl);
}
}
-
+
tokenTargetUrl = context.getInitParameter(TOKEN_TARGET_URL);
String clientData = context.getInitParameter(TOKEN_CLIENT_DATA);
@@ -115,22 +120,18 @@ public class TokenResource {
JWTokenAuthority ts = services.getService(GatewayServices.TOKEN_SERVICE);
Principal p = ((HttpServletRequest)request).getUserPrincipal();
long expires = getExpiry();
-
+
try {
JWT token = null;
- if (targetAudiences == null || targetAudiences.length == 0) {
- token = ts.issueToken(p, "RS256", getExpiry());
+ if (targetAudiences.isEmpty()) {
+ token = ts.issueToken(p, "RS256", expires);
} else {
- ArrayList<String> aud = new ArrayList<String>();
- for (int i = 0; i < targetAudiences.length; i++) {
- aud.add(targetAudiences[i]);
- }
- token = ts.issueToken(p, aud, "RS256", expires);
+ token = ts.issueToken(p, targetAudiences, "RS256", expires);
}
if (token != null) {
String accessToken = token.toString();
-
+
HashMap<String, Object> map = new HashMap<>();
map.put(ACCESS_TOKEN, accessToken);
map.put(TOKEN_TYPE, BEARER);
@@ -141,7 +142,7 @@ public class TokenResource {
if (tokenClientDataMap != null) {
map.putAll(tokenClientDataMap);
}
-
+
String jsonResponse = JsonUtils.renderAsJsonString(map);
response.getWriter().write(jsonResponse);
http://git-wip-us.apache.org/repos/asf/knox/blob/3557612d/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceResourceTest.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceResourceTest.java b/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceResourceTest.java
index 2b4fea1..9faa073 100644
--- a/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceResourceTest.java
+++ b/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceResourceTest.java
@@ -18,17 +18,63 @@
package org.apache.hadoop.gateway.service.knoxtoken;
import org.apache.hadoop.gateway.service.knoxtoken.TokenResource;
+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.services.security.token.impl.JWTToken;
+import org.easymock.EasyMock;
import org.junit.Assert;
+import org.junit.BeforeClass;
import org.junit.Test;
+import com.nimbusds.jose.JWSSigner;
+import com.nimbusds.jose.JWSVerifier;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.crypto.RSASSAVerifier;
+
import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.*;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
/**
- *
+ * Some tests for the token service
*/
public class TokenServiceResourceTest {
+ protected static RSAPublicKey publicKey;
+ protected static RSAPrivateKey privateKey;
+
+ @BeforeClass
+ public static void setup() throws Exception, NoSuchAlgorithmException {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(1024);
+ KeyPair KPair = kpg.generateKeyPair();
+
+ publicKey = (RSAPublicKey) KPair.getPublic();
+ privateKey = (RSAPrivateKey) KPair.getPrivate();
+ }
+
@Test
public void testTokenService() throws Exception {
Assert.assertTrue(true);
@@ -50,4 +96,212 @@ public class TokenServiceResourceTest {
tr.addClientDataToMap("".split(","), clientDataMap);
Assert.assertTrue(clientDataMap.size() == 0);
}
+
+ @Test
+ public void testGetToken() throws Exception {
+ TokenResource tr = new TokenResource();
+
+ ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+ //tr.context = context;
+ // tr.init();
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes();
+ Principal principal = EasyMock.createNiceMock(Principal.class);
+ EasyMock.expect(principal.getName()).andReturn("alice").anyTimes();
+ EasyMock.expect(request.getUserPrincipal()).andReturn(principal).anyTimes();
+
+ GatewayServices services = EasyMock.createNiceMock(GatewayServices.class);
+ EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(services);
+
+ JWTokenAuthority authority = new TestJWTokenAuthority(publicKey, privateKey);
+ EasyMock.expect(services.getService(GatewayServices.TOKEN_SERVICE)).andReturn(authority);
+
+ StringWriter writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.getWriter()).andReturn(printWriter);
+
+ EasyMock.replay(principal, services, context, request, response);
+
+ tr.request = request;
+ tr.response = response;
+
+ // Issue a token
+ Response retResponse = tr.doGet();
+
+ assertEquals(200, retResponse.getStatus());
+
+ // Parse the response
+ String retString = writer.toString();
+ String accessToken = getTagValue(retString, "access_token");
+ assertNotNull(accessToken);
+ String expiry = getTagValue(retString, "expires_in");
+ assertNotNull(expiry);
+
+ // Verify the token
+ JWTToken parsedToken = new JWTToken(accessToken);
+ assertEquals("alice", parsedToken.getSubject());
+ assertTrue(authority.verifyToken(parsedToken));
+ }
+
+ @Test
+ public void testAudiences() throws Exception {
+
+ ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(context.getInitParameter("knox.token.audiences")).andReturn("recipient1,recipient2");
+ EasyMock.expect(context.getInitParameter("knox.token.ttl")).andReturn(null);
+ EasyMock.expect(context.getInitParameter("knox.token.target.url")).andReturn(null);
+ EasyMock.expect(context.getInitParameter("knox.token.client.data")).andReturn(null);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes();
+ Principal principal = EasyMock.createNiceMock(Principal.class);
+ EasyMock.expect(principal.getName()).andReturn("alice").anyTimes();
+ EasyMock.expect(request.getUserPrincipal()).andReturn(principal).anyTimes();
+
+ GatewayServices services = EasyMock.createNiceMock(GatewayServices.class);
+ EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).andReturn(services);
+
+ JWTokenAuthority authority = new TestJWTokenAuthority(publicKey, privateKey);
+ EasyMock.expect(services.getService(GatewayServices.TOKEN_SERVICE)).andReturn(authority);
+
+ StringWriter writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.getWriter()).andReturn(printWriter);
+
+ EasyMock.replay(principal, services, context, request, response);
+
+ TokenResource tr = new TokenResource();
+ tr.request = request;
+ tr.response = response;
+ tr.context = context;
+ tr.init();
+
+ // Issue a token
+ Response retResponse = tr.doGet();
+
+ assertEquals(200, retResponse.getStatus());
+
+ // Parse the response
+ String retString = writer.toString();
+ String accessToken = getTagValue(retString, "access_token");
+ assertNotNull(accessToken);
+ String expiry = getTagValue(retString, "expires_in");
+ assertNotNull(expiry);
+
+ // Verify the token
+ JWTToken parsedToken = new JWTToken(accessToken);
+ assertEquals("alice", parsedToken.getSubject());
+ assertTrue(authority.verifyToken(parsedToken));
+
+ // Verify the audiences
+ List<String> audiences = Arrays.asList(parsedToken.getAudienceClaims());
+ assertEquals(2, audiences.size());
+ assertTrue(audiences.contains("recipient1"));
+ assertTrue(audiences.contains("recipient2"));
+ }
+
+ private String getTagValue(String token, String tagName) {
+ String searchString = tagName + "\":";
+ String value = token.substring(token.indexOf(searchString) + searchString.length());
+ if (value.startsWith("\"")) {
+ value = value.substring(1);
+ }
+ if (value.contains("\"")) {
+ return value.substring(0, value.indexOf("\""));
+ } else if (value.contains(",")) {
+ return value.substring(0, value.indexOf(","));
+ } else {
+ return value.substring(0, value.length() - 1);
+ }
+ }
+
+ private static class TestJWTokenAuthority implements JWTokenAuthority {
+
+ private RSAPublicKey publicKey;
+ private RSAPrivateKey privateKey;
+
+ public TestJWTokenAuthority(RSAPublicKey publicKey, RSAPrivateKey privateKey) {
+ this.publicKey = publicKey;
+ this.privateKey = privateKey;
+ }
+
+ @Override
+ public JWTToken issueToken(Subject subject, String algorithm)
+ throws TokenServiceException {
+ Principal p = (Principal) subject.getPrincipals().toArray()[0];
+ return issueToken(p, algorithm);
+ }
+
+ @Override
+ public JWTToken issueToken(Principal p, String algorithm)
+ throws TokenServiceException {
+ return issueToken(p, null, algorithm);
+ }
+
+ @Override
+ public JWTToken issueToken(Principal p, String audience, String algorithm)
+ throws TokenServiceException {
+ return issueToken(p, audience, algorithm, -1);
+ }
+
+ @Override
+ public boolean verifyToken(JWTToken token) throws TokenServiceException {
+ JWSVerifier verifier = new RSASSAVerifier(publicKey);
+ return token.verify(verifier);
+ }
+
+ @Override
+ public JWTToken issueToken(Principal p, String audience, String algorithm,
+ long expires) throws TokenServiceException {
+ ArrayList<String> audiences = null;
+ if (audience != null) {
+ audiences = new ArrayList<String>();
+ audiences.add(audience);
+ }
+ return issueToken(p, audiences, algorithm, expires);
+ }
+
+ @Override
+ public JWTToken issueToken(Principal p, List<String> audiences, String algorithm,
+ long expires) throws TokenServiceException {
+ String[] claimArray = new String[4];
+ claimArray[0] = "KNOXSSO";
+ claimArray[1] = p.getName();
+ claimArray[2] = null;
+ if (expires == -1) {
+ claimArray[3] = null;
+ } else {
+ claimArray[3] = String.valueOf(expires);
+ }
+
+ JWTToken token = null;
+ if ("RS256".equals(algorithm)) {
+ token = new JWTToken("RS256", claimArray, audiences);
+ JWSSigner signer = new RSASSASigner(privateKey);
+ token.sign(signer);
+ } else {
+ throw new TokenServiceException("Cannot issue token - Unsupported algorithm");
+ }
+
+ return token;
+ }
+
+ @Override
+ public JWT issueToken(Principal p, String algorithm, long expiry)
+ throws TokenServiceException {
+ return issueToken(p, Collections.<String>emptyList(), algorithm, expiry);
+ }
+
+ @Override
+ public boolean verifyToken(JWTToken token, RSAPublicKey publicKey) throws TokenServiceException {
+ JWSVerifier verifier = new RSASSAVerifier(publicKey);
+ return token.verify(verifier);
+ }
+
+ }
+
+
}