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