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/09/05 11:09:44 UTC
directory-kerby git commit: DIRKRB-651 - Add support to send a JWT
AccessToken via the GSS API
Repository: directory-kerby
Updated Branches:
refs/heads/trunk c4c43ced6 -> 515b3f2f8
DIRKRB-651 - Add support to send a JWT AccessToken via the GSS API
Project: http://git-wip-us.apache.org/repos/asf/directory-kerby/repo
Commit: http://git-wip-us.apache.org/repos/asf/directory-kerby/commit/515b3f2f
Tree: http://git-wip-us.apache.org/repos/asf/directory-kerby/tree/515b3f2f
Diff: http://git-wip-us.apache.org/repos/asf/directory-kerby/diff/515b3f2f
Branch: refs/heads/trunk
Commit: 515b3f2f86f6d5a20714a04bedca5757fa832280
Parents: c4c43ce
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Tue Sep 5 12:09:03 2017 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Tue Sep 5 12:09:03 2017 +0100
----------------------------------------------------------------------
.../integration/test/KerbyTokenAppTest.java | 126 +++++++++++++++++++
.../kerb/integration/test/TokenAppTest.java | 88 +++++++++++++
.../kerberos/kerb/gss/impl/GssContext.java | 4 +-
.../kerberos/kerb/gss/impl/GssInitCred.java | 19 ++-
.../kerby/kerberos/kerb/gss/impl/GssUtil.java | 54 ++++++--
5 files changed, 275 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/515b3f2f/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
new file mode 100644
index 0000000..b0033f4
--- /dev/null
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/KerbyTokenAppTest.java
@@ -0,0 +1,126 @@
+/**
+ * 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 java.io.InputStream;
+import java.security.PrivateKey;
+import java.security.PrivilegedAction;
+import java.security.Provider;
+import java.security.interfaces.RSAPrivateKey;
+import java.util.Collections;
+
+import javax.security.auth.Subject;
+
+import org.apache.kerby.kerberos.kerb.KrbRuntime;
+import org.apache.kerby.kerberos.kerb.common.PrivateKeyReader;
+import org.apache.kerby.kerberos.kerb.gss.KerbyGssProvider;
+import org.apache.kerby.kerberos.kerb.integration.test.gss.GssAppClient;
+import org.apache.kerby.kerberos.kerb.integration.test.gss.GssAppServer;
+import org.apache.kerby.kerberos.kerb.provider.TokenEncoder;
+import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
+import org.apache.kerby.kerberos.kerb.type.base.TokenFormat;
+import org.apache.kerby.kerberos.provider.token.JwtTokenEncoder;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertTrue;
+
+public class KerbyTokenAppTest extends TokenAppTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(KerbyGssAppTest.class);
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ Provider provider = new KerbyGssProvider();
+ java.security.Security.insertProviderAt(provider, 1);
+ super.setUp();
+ }
+
+ // Here the client is sending a JWT token to the service as an "access token", to be
+ // inserted into the AuthorizationData part of the service ticket.
+ @Test
+ public void testJwtAccessToken() throws Exception {
+ runAppClientWithToken(createAppClient());
+ }
+
+ private void runAppClientWithToken(final AppClient appClient) throws Exception {
+ Subject subject = loginClientUsingPassword();
+
+ // Get an AuthToken
+ AuthToken authToken = issueToken(getClientPrincipal());
+ authToken.isAcToken(true);
+ authToken.isIdToken(false);
+ authToken.setAudiences(Collections.singletonList(getServerPrincipal()));
+ KrbToken krbToken = new KrbToken(authToken, TokenFormat.JWT);
+
+ // Sign it
+ try (InputStream is = this.getClass().getResource("/private_key.pem").openStream()) {
+ PrivateKey signKey = PrivateKeyReader.loadPrivateKey(is);
+ krbToken.setTokenValue(signToken(authToken, signKey));
+ }
+
+ // Add KrbToken to the private creds
+ subject.getPrivateCredentials().add(krbToken);
+
+ Subject.doAs(subject, new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ appClient.run();
+ } catch (Exception ex) {
+ LOG.error(ex.toString());
+ }
+ return null;
+ }
+ });
+
+ assertTrue("Client successfully connected and authenticated to server",
+ appClient.isTestOK());
+ }
+
+ private byte[] signToken(AuthToken authToken, PrivateKey signKey) throws Exception {
+ TokenEncoder tokenEncoder = KrbRuntime.getTokenProvider().createTokenEncoder();
+ assertTrue(tokenEncoder instanceof JwtTokenEncoder);
+
+ ((JwtTokenEncoder) tokenEncoder).setSignKey((RSAPrivateKey) signKey);
+ return tokenEncoder.encodeAsBytes(authToken);
+ }
+
+ @Override
+ protected AppServer createAppServer() throws Exception {
+ return new GssAppServer(new String[] {
+ String.valueOf(getServerPort()),
+ getServerPrincipal()
+ });
+ }
+
+ private AppClient createAppClient() throws Exception {
+ return new GssAppClient(new String[] {
+ getHostname(),
+ String.valueOf(getServerPort()),
+ getClientPrincipal(),
+ getServerPrincipal()
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/515b3f2f/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenAppTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenAppTest.java b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenAppTest.java
new file mode 100644
index 0000000..55298f9
--- /dev/null
+++ b/kerby-kerb/integration-test/src/test/java/org/apache/kerby/kerberos/kerb/integration/test/TokenAppTest.java
@@ -0,0 +1,88 @@
+/**
+ * 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 org.apache.kerby.util.NetworkUtil;
+import org.junit.Assert;
+import org.junit.Before;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.Subject;
+import java.security.PrivilegedAction;
+
+public abstract class TokenAppTest extends TokenLoginTestBase {
+ private static final Logger LOG = LoggerFactory.getLogger(TokenAppTest.class);
+ private int serverPort;
+ protected AppServer appServer;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ serverPort = NetworkUtil.getServerPort();
+
+ setupAppServer();
+ }
+
+ protected int getServerPort() {
+ return serverPort;
+ }
+
+ protected void setupAppServer() throws Exception {
+ Subject subject = loginServiceUsingKeytab();
+ Subject.doAs(subject, new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ appServer = createAppServer();
+ appServer.start();
+ } catch (Exception ex) {
+ LOG.error(ex.toString());
+ }
+
+ return null;
+ }
+ });
+ }
+
+ protected abstract AppServer createAppServer() throws Exception;
+
+ protected void runAppClient(final AppClient appClient) throws Exception {
+ Subject subject = loginClientUsingTicketCache();
+ Subject.doAs(subject, new PrivilegedAction<Object>() {
+ @Override
+ public Object run() {
+ try {
+ appClient.run();
+ } catch (Exception ex) {
+ LOG.error(ex.toString());
+ }
+ return null;
+ }
+ });
+
+ Assert.assertTrue("Client successfully connected and authenticated to server",
+ appClient.isTestOK());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/515b3f2f/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssContext.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssContext.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssContext.java
index 138bdd2..3da77d2 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssContext.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssContext.java
@@ -278,7 +278,9 @@ public class GssContext implements GSSContextSpi {
sgtTicket = GssUtil.getSgtCredentialFromContext(caller, clientPrincipal.getName(), serviceName);
if (sgtTicket == null) {
- sgtTicket = GssUtil.applySgtCredential(((GssInitCred) myCred).getKerberosTicket(), serviceName);
+ sgtTicket = GssUtil.applySgtCredential(((GssInitCred) myCred).getKerberosTicket(),
+ ((GssInitCred) myCred).getKrbToken(),
+ serviceName);
// add this service credential to context
final KerberosTicket ticket =
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/515b3f2f/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssInitCred.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssInitCred.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssInitCred.java
index 225e581..aa41718 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssInitCred.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssInitCred.java
@@ -19,32 +19,41 @@
*/
package org.apache.kerby.kerberos.kerb.gss.impl;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSName;
import sun.security.jgss.GSSCaller;
+import java.util.Set;
+
import javax.security.auth.kerberos.KerberosTicket;
public final class GssInitCred extends GssCredElement {
private KerberosTicket ticket;
+ private KrbToken krbToken;
- private GssInitCred(GSSCaller caller, GssNameElement name, KerberosTicket ticket, int lifeTime) {
+ private GssInitCred(GSSCaller caller, GssNameElement name,
+ KerberosTicket ticket, KrbToken krbToken, int lifeTime) {
super(caller, name);
this.ticket = ticket;
this.initLifeTime = lifeTime;
+ this.krbToken = krbToken;
}
public static GssInitCred getInstance(GSSCaller caller, GssNameElement name, int lifeTime) throws GSSException {
+ Set<KrbToken> krbTokens = CredUtils.getContextCredentials(KrbToken.class);
+ KrbToken krbToken = krbTokens != null && !krbTokens.isEmpty() ? krbTokens.iterator().next() : null;
+
if (name == null) {
KerberosTicket ticket = CredUtils.getKerberosTicketFromContext(caller, null, null);
GssNameElement clientName = GssNameElement.getInstance(ticket.getClient().getName(), GSSName.NT_USER_NAME);
- return new GssInitCred(caller, clientName, ticket, lifeTime);
+ return new GssInitCred(caller, clientName, ticket, krbToken, lifeTime);
}
KerberosTicket ticket = CredUtils.getKerberosTicketFromContext(caller, name.getPrincipalName().getName(), null);
- return new GssInitCred(caller, name, ticket, lifeTime);
+ return new GssInitCred(caller, name, ticket, krbToken, lifeTime);
}
public boolean isInitiatorCredential() throws GSSException {
@@ -58,4 +67,8 @@ public final class GssInitCred extends GssCredElement {
public KerberosTicket getKerberosTicket() {
return ticket;
}
+
+ public KrbToken getKrbToken() {
+ return krbToken;
+ }
}
http://git-wip-us.apache.org/repos/asf/directory-kerby/blob/515b3f2f/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
index 099c79b..ca3c509 100644
--- a/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
+++ b/kerby-kerb/kerb-gssapi/src/main/java/org/apache/kerby/kerberos/kerb/gss/impl/GssUtil.java
@@ -21,12 +21,14 @@ package org.apache.kerby.kerberos.kerb.gss.impl;
import org.apache.kerby.kerberos.kerb.KrbException;
import org.apache.kerby.kerberos.kerb.client.KrbClientBase;
+import org.apache.kerby.kerberos.kerb.client.KrbTokenClient;
import org.apache.kerby.kerberos.kerb.type.KerberosTime;
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.EncryptionKey;
import org.apache.kerby.kerberos.kerb.type.base.HostAddress;
import org.apache.kerby.kerberos.kerb.type.base.HostAddresses;
+import org.apache.kerby.kerberos.kerb.type.base.KrbToken;
import org.apache.kerby.kerberos.kerb.type.base.PrincipalName;
import org.apache.kerby.kerberos.kerb.type.kdc.EncAsRepPart;
import org.apache.kerby.kerberos.kerb.type.kdc.EncKdcRepPart;
@@ -217,22 +219,37 @@ public class GssUtil {
/**
* Apply SgtTicket by sending TGS_REQ to KDC
* @param ticket
+ * @param krbToken
* @param service
* @return
*/
- public static SgtTicket applySgtCredential(KerberosTicket ticket, String service) throws GSSException {
+ public static SgtTicket applySgtCredential(KerberosTicket ticket, KrbToken krbToken,
+ String service) throws GSSException {
TgtTicket tgt = getTgtTicketFromKerberosTicket(ticket);
- return applySgtCredential(tgt, service);
+ if (krbToken == null) {
+ return applySgtCredential(tgt, service);
+ }
+
+ return applySgtCredential(tgt, krbToken, service);
}
public static SgtTicket applySgtCredential(TgtTicket tgt, String server) throws GSSException {
KrbClientBase client = getKrbClient();
- SgtTicket sgt = null;
try {
client.init();
- sgt = client.requestSgt(tgt, server);
- return sgt;
+ return client.requestSgt(tgt, server);
+ } catch (KrbException e) {
+ throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
+ }
+ }
+
+ public static SgtTicket applySgtCredential(TgtTicket tgt, KrbToken krbToken, String server) throws GSSException {
+ KrbTokenClient client = getKrbTokenClient();
+
+ try {
+ client.init();
+ return client.requestSgt(krbToken, server, tgt);
} catch (KrbException e) {
throw new GSSException(GSSException.FAILURE, -1, e.getMessage());
}
@@ -302,21 +319,34 @@ public class GssUtil {
}
public static KrbClientBase getKrbClient() {
- KrbClientBase client;
try {
String systemProperty = getSystemProperty("java.security.krb5.conf");
if (systemProperty != null) {
File confSpecified = new File(systemProperty);
if (confSpecified.exists()) {
- client = new KrbClientBase(confSpecified);
- } else {
- client = new KrbClientBase(); // get configure file from environment variable or default path
+ return new KrbClientBase(confSpecified);
+ }
+ }
+
+ // get configuration file from environment variable or default path
+ return new KrbClientBase();
+ } catch (KrbException e) {
+ return null;
+ }
+ }
+
+ public static KrbTokenClient getKrbTokenClient() {
+ try {
+ String systemProperty = getSystemProperty("java.security.krb5.conf");
+ if (systemProperty != null) {
+ File confSpecified = new File(systemProperty);
+ if (confSpecified.exists()) {
+ return new KrbTokenClient(confSpecified);
}
- } else {
- client = new KrbClientBase();
}
- return client;
+ // get configuration file from environment variable or default path
+ return new KrbTokenClient();
} catch (KrbException e) {
return null;
}