You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by co...@apache.org on 2017/07/05 15:27:47 UTC
[2/3] directory-kerby git commit: DIRKRB-632 - Adding unit tests for
identity and access tokens
DIRKRB-632 - Adding unit tests for identity and access tokens
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/7c89f0a9
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/7c89f0a9
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/7c89f0a9
Branch: refs/heads/trunk
Commit: 7c89f0a9d1f9a77730e561e40925447f30498c95
Parents: 44c142b
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Wed Jul 5 16:11:50 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Wed Jul 5 16:11:50 2017 +0100
----------------------------------------------------------------------
.../kerb/integration/test/JWTTokenTest.java | 407 +++++++++++++++++++
.../integration/test/TokenLoginTestBase.java | 6 +-
.../kerby/kerberos/kerb/server/KdcTestBase.java | 17 +-
3 files changed, 423 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
new file mode 100644
index 0000000..04ba1d0
--- /dev/null
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/JWTTokenTest.java
@@ -0,0 +1,407 @@
+/**
+ * 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.kerby.kerberos.kerb.integration.test;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.PrivateKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Collections;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.KrbRuntime;
+import org.apache.kerby.kerberos.kerb.ccache.Credential;
+import org.apache.kerby.kerberos.kerb.ccache.CredentialCache;
+import org.apache.kerby.kerberos.kerb.client.KrbClient;
+import org.apache.kerby.kerberos.kerb.client.KrbTokenClient;
+import org.apache.kerby.kerberos.kerb.common.EncryptionUtil;
+import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader;
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
+import org.apache.kerby.kerberos.kerb.type.ad.AdToken;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationData;
+import org.apache.kerby.kerberos.kerb.type.ad.AuthorizationDataEntry;
+import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
+import org.apache.kerby.kerberos.kerb.type.base.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.type.base.KeyUsage;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import org.apache.kerby.kerberos.kerb.type.base.TokenFormat;
+import org.apache.kerby.kerberos.kerb.type.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.type.ticket.SgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.TgtTicket;
+import org.apache.kerby.kerberos.kerb.type.ticket.Ticket;
+import org.apache.kerby.kerberos.provider.token.JwtTokenEncoder;
+
+/**
+ * Some tests for JWT tokens using the Kerby client API
+ */
+public class JWTTokenTest extends TokenLoginTestBase {
+
+ @org.junit.Test
+ public void accessToken() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ SgtTicket tkt = tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ assertTrue(tkt != null);
+
+ // Decrypt the ticket
+ Ticket ticket = tkt.getTicket();
+ EncryptionKey key = EncryptionHandler.string2Key(getServerPrincipal(), getServerPassword(),
+ ticket.getEncryptedEncPart().getEType());
+
+ EncTicketPart encPart =
+ EncryptionUtil.unseal(ticket.getEncryptedEncPart(),
+ key, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
+
+ // Examine the authorization data
+ AuthorizationData authzData = encPart.getAuthorizationData();
+ assertEquals(1, authzData.getElements().size());
+ AuthorizationDataEntry dataEntry = authzData.getElements().iterator().next();
+ AdToken token = dataEntry.getAuthzDataAs(AdToken.class);
+ KrbToken decodedKrbToken = token.getToken();
+ assertEquals(getClientPrincipal(), decodedKrbToken.getSubject());
+ assertEquals(getServerPrincipal(), decodedKrbToken.getAudiences().get(0));
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void accessTokenInvalidAudience() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal() + "_"));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an invalid audience");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ @org.junit.Ignore
+ public void accessTokenInvalidSignature() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ File signKeyFile = new File(this.getClass().getResource("/kdckeytest.pem").getPath());
+ krbToken.setTokenValue(signToken(authToken, signKeyFile));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an invalid signature");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void accessTokenUnknownIssuer() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token with an invalid audience
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ authToken.setIssuer("unknown-issuer");
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a SGT using the JWT
+ try {
+ tokenClient.requestSgt(krbToken, getServerPrincipal(), cCacheFile.getPath());
+ fail("Failure expected on an unknown issuer");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityToken() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ tgt = tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+
+ // Now get a SGT using the TGT
+ SgtTicket tkt = tokenClient.requestSgt(tgt, getServerPrincipal());
+ assertTrue(tkt != null);
+
+ // Decrypt the ticket
+ Ticket ticket = tkt.getTicket();
+ EncryptionKey key = EncryptionHandler.string2Key(getServerPrincipal(), getServerPassword(),
+ ticket.getEncryptedEncPart().getEType());
+
+ EncTicketPart encPart =
+ EncryptionUtil.unseal(ticket.getEncryptedEncPart(),
+ key, KeyUsage.KDC_REP_TICKET, EncTicketPart.class);
+
+ // Check the authorization data is not present
+ AuthorizationData authzData = encPart.getAuthorizationData();
+ assertNull(authzData);
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityTokenInvalidAudience() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.setAudiences(Collections.singletonList(authToken.getAudiences().get(0) + "_"));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ try {
+ tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+ fail("Failure expected on an invalid audience");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ @org.junit.Test
+ public void identityTokenUnknownIssuer() throws Exception {
+
+ KrbClient client = getKrbClient();
+
+ // Get a TGT
+ TgtTicket tgt = client.requestTgt(getClientPrincipal(), getClientPassword());
+ assertNotNull(tgt);
+
+ // Write to cache
+ Credential credential = new Credential(tgt);
+ CredentialCache cCache = new CredentialCache();
+ cCache.addCredential(credential);
+ cCache.setPrimaryPrincipal(tgt.getClientPrincipal());
+
+ File cCacheFile = File.createTempFile("krb5_" + getClientPrincipal(), "cc");
+ cCache.store(cCacheFile);
+
+ KrbTokenClient tokenClient = new KrbTokenClient(client);
+
+ tokenClient.setKdcHost(client.getSetting().getKdcHost());
+ tokenClient.setKdcTcpPort(client.getSetting().getKdcTcpPort());
+
+ tokenClient.setKdcRealm(client.getSetting().getKdcRealm());
+ tokenClient.init();
+
+ // Create a JWT token
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.setIssuer("unknown-issuer");
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+ krbToken.setTokenValue(signToken(authToken, getSignKeyFile()));
+
+ // Now get a TGT using the JWT token
+ try {
+ tokenClient.requestTgt(krbToken, cCacheFile.getPath());
+ fail("Failure expected on an unknown issuer");
+ } catch (KrbException ex) { //NOPMD
+ // expected
+ }
+
+ cCacheFile.delete();
+ }
+
+ private byte[] signToken(AuthToken authToken, File signKeyFile) throws Exception {
+ TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+ assertTrue(tokenEncoder instanceof JwtTokenEncoder);
+
+ InputStream is = Files.newInputStream(signKeyFile.toPath());
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+
+ ((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
+ return tokenEncoder.encodeAsBytes(authToken);
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
index 140a81d..044870b 100644
--- a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenLoginTestBase.java
@@ -106,7 +106,7 @@ public class TokenLoginTestBase extends LoginTestBase {
return tokenStr;
}
- private AuthToken issueToken(String principal) {
+ protected AuthToken issueToken(String principal) {
AuthToken authToken = KrbRuntime.getTokenProvider().createTokenFactory().createToken();
String iss = "token-service";
@@ -174,4 +174,8 @@ public class TokenLoginTestBase extends LoginTestBase {
protected File getTGTCache() {
return tgtCache;
}
+
+ protected File getSignKeyFile() {
+ return signKeyFile;
+ }
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/7c89f0a9/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java b/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
index c4a87be..547db27 100644
--- a/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
+++ b/kerby-kerb/kerb-kdc-test/src/test/java/org/apache/kerby/kerberos/kerb/server/KdcTestBase.java
@@ -6,16 +6,16 @@
* 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.
- *
+ * under the License.
+ *
*/
package org.apache.kerby.kerberos.kerb.server;
@@ -41,6 +41,7 @@ public abstract class KdcTestBase {
private final String clientPrincipalName = "drankye";
private final String clientPrincipal =
clientPrincipalName + "@" + TestKdcServer.KDC_REALM;
+ private final String serverPassword = "654321";
private final String serverPrincipalName = "test-service";
private final String serverPrincipal;
@@ -112,6 +113,10 @@ public abstract class KdcTestBase {
return clientPassword;
}
+ protected String getServerPassword() {
+ return serverPassword;
+ }
+
protected String getServerPrincipal() {
return serverPrincipal;
}
@@ -127,7 +132,7 @@ public abstract class KdcTestBase {
protected boolean allowTcp() {
return true;
}
-
+
@Before
public void setUp() throws Exception {
setUpKdcServer();
@@ -159,7 +164,7 @@ public abstract class KdcTestBase {
}
protected void createPrincipals() throws KrbException {
- kdcServer.createPrincipals(serverPrincipal);
+ kdcServer.createPrincipal(serverPrincipal, serverPassword);
kdcServer.createPrincipal(clientPrincipal, clientPassword);
}