From 943d3f641cd7256ee6c9c0fe72314aee7ce15e91 Mon Sep 17 00:00:00 2001 From: Owen O'Malley Date: Fri, 14 Feb 2014 21:25:12 +0000 Subject: [PATCH] HADOOP-10342. Add a new method to UGI to use a Kerberos login subject to build a new UGI. (Larry McCay via omalley) git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1568525 13f79535-47bb-0310-9956-ffa450edef68 --- .../hadoop-common/CHANGES.txt | 3 ++ .../java/org/apache/hadoop/ipc/Client.java | 2 +- .../hadoop/security/UserGroupInformation.java | 38 ++++++++++++++++- .../security/TestUGIWithSecurityOn.java | 42 +++++++++++++++++++ .../security/TestUserGroupInformation.java | 11 +++++ 5 files changed, 94 insertions(+), 2 deletions(-) diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 4e6dc469ebe..32d1ae1df05 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -118,6 +118,9 @@ Trunk (Unreleased) HADOOP-10325. Improve jenkins javadoc warnings from test-patch.sh (cmccabe) + HADOOP-10342. Add a new method to UGI to use a Kerberos login subject to + build a new UGI. (Larry McCay via omalley) + BUG FIXES HADOOP-9451. Fault single-layer config if node group topology is enabled. diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java index 45d0cd1f466..b3cc04c4eb0 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java @@ -649,7 +649,7 @@ public class Client { // try re-login if (UserGroupInformation.isLoginKeytabBased()) { UserGroupInformation.getLoginUser().reloginFromKeytab(); - } else { + } else if (UserGroupInformation.isLoginTicketBased()) { UserGroupInformation.getLoginUser().reloginFromTicketCache(); } // have granularity of milliseconds diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java index 178a4723506..a8bbd6c25e5 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java @@ -702,6 +702,35 @@ public class UserGroupInformation { } } + /** + * Create a UserGroupInformation from a Subject with Kerberos principal. + * + * @param user The KerberosPrincipal to use in UGI + * + * @throws IOException if the kerberos login fails + */ + public static UserGroupInformation getUGIFromSubject(Subject subject) + throws IOException { + if (subject == null) { + throw new IOException("Subject must not be null"); + } + + if (subject.getPrincipals(KerberosPrincipal.class).isEmpty()) { + throw new IOException("Provided Subject must contain a KerberosPrincipal"); + } + + KerberosPrincipal principal = + subject.getPrincipals(KerberosPrincipal.class).iterator().next(); + + User ugiUser = new User(principal.getName(), + AuthenticationMethod.KERBEROS, null); + subject.getPrincipals().add(ugiUser); + UserGroupInformation ugi = new UserGroupInformation(subject); + ugi.setLogin(null); + ugi.setAuthenticationMethod(AuthenticationMethod.KERBEROS); + return ugi; + } + /** * Get the currently logged in user. * @return the logged in user @@ -1101,6 +1130,14 @@ public class UserGroupInformation { return getLoginUser().isKeytab; } + /** + * Did the login happen via ticket cache + * @return true or false + */ + public static boolean isLoginTicketBased() throws IOException { + return getLoginUser().isKrbTkt; + } + /** * Create a user from a login name. It is intended to be used for remote * users in RPC, since it won't have any credentials. @@ -1619,5 +1656,4 @@ public class UserGroupInformation { System.out.println("Keytab " + loginUser.isKeytab); } } - } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGIWithSecurityOn.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGIWithSecurityOn.java index a1585933515..ae7bf084b8d 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGIWithSecurityOn.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGIWithSecurityOn.java @@ -17,8 +17,14 @@ package org.apache.hadoop.security; import java.io.IOException; +import java.security.PrivilegedAction; +import java.util.Set; + +import javax.security.auth.kerberos.KerberosPrincipal; import junit.framework.Assert; +import static org.junit.Assert.*; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; @@ -72,4 +78,40 @@ public class TestUGIWithSecurityOn { ex.printStackTrace(); } } + + @Test + public void testGetUGIFromKerberosSubject() throws IOException { + String user1keyTabFilepath = System.getProperty("kdc.resource.dir") + + "/keytabs/user1.keytab"; + + UserGroupInformation ugi = UserGroupInformation + .loginUserFromKeytabAndReturnUGI("user1@EXAMPLE.COM", + user1keyTabFilepath); + Set principals = ugi.getSubject().getPrincipals( + KerberosPrincipal.class); + if (principals.isEmpty()) { + Assert.fail("There should be a kerberos principal in the subject."); + } + else { + UserGroupInformation ugi2 = UserGroupInformation.getUGIFromSubject( + ugi.getSubject()); + if (ugi2 != null) { + ugi2.doAs(new PrivilegedAction() { + + @Override + public Object run() { + try { + UserGroupInformation ugi3 = UserGroupInformation.getCurrentUser(); + String doAsUserName = ugi3.getUserName(); + assertEquals(doAsUserName, "user1@EXAMPLE.COM"); + System.out.println("DO AS USERNAME: " + doAsUserName); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + }); + } + } + } } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java index 35568c28839..614054f7c27 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java @@ -28,6 +28,7 @@ import org.apache.hadoop.util.Shell; import org.junit.*; import javax.security.auth.Subject; +import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.login.AppConfigurationEntry; import javax.security.auth.login.LoginContext; import java.io.BufferedReader; @@ -768,6 +769,16 @@ public class TestUserGroupInformation { }); } + @Test (timeout = 30000) + public void testGetUGIFromSubject() throws Exception { + KerberosPrincipal p = new KerberosPrincipal("guest"); + Subject subject = new Subject(); + subject.getPrincipals().add(p); + UserGroupInformation ugi = UserGroupInformation.getUGIFromSubject(subject); + assertNotNull(ugi); + assertEquals("guest@DEFAULT.REALM", ugi.getUserName()); + } + /** Test hasSufficientTimeElapsed method */ @Test (timeout = 30000) public void testHasSufficientTimeElapsed() throws Exception {