|
@@ -38,7 +38,9 @@ import java.util.Set;
|
|
|
|
|
|
import javax.security.auth.Subject;
|
|
import javax.security.auth.Subject;
|
|
import javax.security.auth.callback.CallbackHandler;
|
|
import javax.security.auth.callback.CallbackHandler;
|
|
|
|
+import javax.security.auth.kerberos.KerberosKey;
|
|
import javax.security.auth.kerberos.KerberosPrincipal;
|
|
import javax.security.auth.kerberos.KerberosPrincipal;
|
|
|
|
+import javax.security.auth.kerberos.KerberosTicket;
|
|
import javax.security.auth.login.AppConfigurationEntry;
|
|
import javax.security.auth.login.AppConfigurationEntry;
|
|
import javax.security.auth.login.LoginContext;
|
|
import javax.security.auth.login.LoginContext;
|
|
import javax.security.auth.login.LoginException;
|
|
import javax.security.auth.login.LoginException;
|
|
@@ -53,6 +55,7 @@ import org.apache.hadoop.conf.Configuration;
|
|
import org.apache.hadoop.fs.Path;
|
|
import org.apache.hadoop.fs.Path;
|
|
import org.apache.hadoop.security.token.Token;
|
|
import org.apache.hadoop.security.token.Token;
|
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
|
import org.apache.hadoop.security.token.TokenIdentifier;
|
|
|
|
+import org.apache.hadoop.util.Shell;
|
|
|
|
|
|
import com.sun.security.auth.NTUserPrincipal;
|
|
import com.sun.security.auth.NTUserPrincipal;
|
|
import com.sun.security.auth.UnixPrincipal;
|
|
import com.sun.security.auth.UnixPrincipal;
|
|
@@ -68,6 +71,10 @@ import com.sun.security.auth.module.Krb5LoginModule;
|
|
@InterfaceStability.Evolving
|
|
@InterfaceStability.Evolving
|
|
public class UserGroupInformation {
|
|
public class UserGroupInformation {
|
|
private static final Log LOG = LogFactory.getLog(UserGroupInformation.class);
|
|
private static final Log LOG = LogFactory.getLog(UserGroupInformation.class);
|
|
|
|
+ /**
|
|
|
|
+ * Percentage of the ticket window to use before we renew ticket.
|
|
|
|
+ */
|
|
|
|
+ private static final float TICKET_RENEW_WINDOW = 0.80f;
|
|
|
|
|
|
/**
|
|
/**
|
|
* A login module that looks at the Kerberos, Unix, or Windows principal and
|
|
* A login module that looks at the Kerberos, Unix, or Windows principal and
|
|
@@ -140,15 +147,13 @@ public class UserGroupInformation {
|
|
private static Configuration conf;
|
|
private static Configuration conf;
|
|
|
|
|
|
|
|
|
|
- public static final long MIN_TIME_BEFORE_RELOGIN = 10 * 60 * 1000L;
|
|
|
|
|
|
+ /** Leave 10 minutes between relogin attempts. */
|
|
|
|
+ private static final long MIN_TIME_BEFORE_RELOGIN = 10 * 60 * 1000L;
|
|
|
|
|
|
/**Environment variable pointing to the token cache file*/
|
|
/**Environment variable pointing to the token cache file*/
|
|
public static final String HADOOP_TOKEN_FILE_LOCATION =
|
|
public static final String HADOOP_TOKEN_FILE_LOCATION =
|
|
"HADOOP_TOKEN_FILE_LOCATION";
|
|
"HADOOP_TOKEN_FILE_LOCATION";
|
|
|
|
|
|
- /** The last relogin attempt */
|
|
|
|
- private long lastReloginTime = 0;
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* A method to initialize the fields that depend on a configuration.
|
|
* A method to initialize the fields that depend on a configuration.
|
|
* Must be called before useKerberos or groups is used.
|
|
* Must be called before useKerberos or groups is used.
|
|
@@ -224,6 +229,9 @@ public class UserGroupInformation {
|
|
private static String keytabFile = null;
|
|
private static String keytabFile = null;
|
|
|
|
|
|
private final Subject subject;
|
|
private final Subject subject;
|
|
|
|
+ // All non-static fields must be read-only caches that come from the subject.
|
|
|
|
+ private final User user;
|
|
|
|
+ private final boolean isKeytab;
|
|
|
|
|
|
private static final String OS_LOGIN_MODULE_NAME;
|
|
private static final String OS_LOGIN_MODULE_NAME;
|
|
private static final Class<? extends Principal> OS_PRINCIPAL_CLASS;
|
|
private static final Class<? extends Principal> OS_PRINCIPAL_CLASS;
|
|
@@ -349,16 +357,11 @@ public class UserGroupInformation {
|
|
}
|
|
}
|
|
|
|
|
|
private LoginContext getLogin() {
|
|
private LoginContext getLogin() {
|
|
- for (User p: subject.getPrincipals(User.class)) {
|
|
|
|
- return p.getLogin();
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
|
|
+ return user.getLogin();
|
|
}
|
|
}
|
|
|
|
|
|
private void setLogin(LoginContext login) {
|
|
private void setLogin(LoginContext login) {
|
|
- for (User p: subject.getPrincipals(User.class)) {
|
|
|
|
- p.setLogin(login);
|
|
|
|
- }
|
|
|
|
|
|
+ user.setLogin(login);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -368,6 +371,8 @@ public class UserGroupInformation {
|
|
*/
|
|
*/
|
|
UserGroupInformation(Subject subject) {
|
|
UserGroupInformation(Subject subject) {
|
|
this.subject = subject;
|
|
this.subject = subject;
|
|
|
|
+ this.user = subject.getPrincipals(User.class).iterator().next();
|
|
|
|
+ this.isKeytab = !subject.getPrivateCredentials(KerberosKey.class).isEmpty();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -391,7 +396,6 @@ public class UserGroupInformation {
|
|
if (loginUser == null) {
|
|
if (loginUser == null) {
|
|
try {
|
|
try {
|
|
Subject subject = new Subject();
|
|
Subject subject = new Subject();
|
|
- loginUser = new UserGroupInformation(subject);
|
|
|
|
LoginContext login;
|
|
LoginContext login;
|
|
if (isSecurityEnabled()) {
|
|
if (isSecurityEnabled()) {
|
|
login = new LoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
|
|
login = new LoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
|
|
@@ -401,7 +405,11 @@ public class UserGroupInformation {
|
|
subject);
|
|
subject);
|
|
}
|
|
}
|
|
login.login();
|
|
login.login();
|
|
|
|
+ loginUser = new UserGroupInformation(subject);
|
|
loginUser.setLogin(login);
|
|
loginUser.setLogin(login);
|
|
|
|
+ loginUser.setAuthenticationMethod(isSecurityEnabled() ?
|
|
|
|
+ AuthenticationMethod.KERBEROS :
|
|
|
|
+ AuthenticationMethod.SIMPLE);
|
|
loginUser = new UserGroupInformation(login.getSubject());
|
|
loginUser = new UserGroupInformation(login.getSubject());
|
|
String fileLocation = System.getenv(HADOOP_TOKEN_FILE_LOCATION);
|
|
String fileLocation = System.getenv(HADOOP_TOKEN_FILE_LOCATION);
|
|
if (fileLocation != null && isSecurityEnabled()) {
|
|
if (fileLocation != null && isSecurityEnabled()) {
|
|
@@ -413,6 +421,7 @@ public class UserGroupInformation {
|
|
loginUser.addToken(token);
|
|
loginUser.addToken(token);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ loginUser.spawnAutoRenewalThreadForUserCreds();
|
|
} catch (LoginException le) {
|
|
} catch (LoginException le) {
|
|
throw new IOException("failure to login", le);
|
|
throw new IOException("failure to login", le);
|
|
}
|
|
}
|
|
@@ -420,6 +429,90 @@ public class UserGroupInformation {
|
|
return loginUser;
|
|
return loginUser;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Is this user logged in from a keytab file?
|
|
|
|
+ * @return true if the credentials are from a keytab file.
|
|
|
|
+ */
|
|
|
|
+ public boolean isFromKeytab() {
|
|
|
|
+ return isKeytab;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**Spawn a thread to do periodic renewals of kerberos credentials*/
|
|
|
|
+ private void spawnAutoRenewalThreadForUserCreds() {
|
|
|
|
+ if (isSecurityEnabled()) {
|
|
|
|
+ //spawn thread only if we have kerb credentials
|
|
|
|
+ if (user.getAuthenticationMethod() == AuthenticationMethod.KERBEROS &&
|
|
|
|
+ !isKeytab) {
|
|
|
|
+ Thread t = new Thread(new Runnable() {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Get the Kerberos TGT
|
|
|
|
+ * @return the user's TGT or null if none was found
|
|
|
|
+ */
|
|
|
|
+ private KerberosTicket getTGT() {
|
|
|
|
+ Set<KerberosTicket> tickets =
|
|
|
|
+ subject.getPrivateCredentials(KerberosTicket.class);
|
|
|
|
+ for(KerberosTicket ticket: tickets) {
|
|
|
|
+ if (SecurityUtil.isOriginalTGT(ticket)) {
|
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
|
+ LOG.debug("Found tgt " + ticket);
|
|
|
|
+ }
|
|
|
|
+ return ticket;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private long getRefreshTime(KerberosTicket tgt) {
|
|
|
|
+ long start = tgt.getStartTime().getTime();
|
|
|
|
+ long end = tgt.getEndTime().getTime();
|
|
|
|
+ return start + (long) ((end - start) * TICKET_RENEW_WINDOW);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void run() {
|
|
|
|
+ String cmd = conf.get("hadoop.kerberos.kinit.command",
|
|
|
|
+ "/usr/kerberos/bin/kinit");
|
|
|
|
+ KerberosTicket tgt = getTGT();
|
|
|
|
+ if (tgt == null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ long nextRefresh = getRefreshTime(tgt);
|
|
|
|
+ while (true) {
|
|
|
|
+ try {
|
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
|
+ LOG.debug("Current time is " + now);
|
|
|
|
+ LOG.debug("Next refresh is " + nextRefresh);
|
|
|
|
+ if (now < nextRefresh) {
|
|
|
|
+ Thread.sleep(nextRefresh - now);
|
|
|
|
+ }
|
|
|
|
+ Shell.execCommand(cmd, "-R");
|
|
|
|
+ LOG.debug("renewed ticket");
|
|
|
|
+ reloginFromTicketCache();
|
|
|
|
+ tgt = getTGT();
|
|
|
|
+ if (tgt == null) {
|
|
|
|
+ LOG.warn("No TGT after renewal. Aborting renew thread for " +
|
|
|
|
+ getUserName());
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ nextRefresh = Math.max(getRefreshTime(tgt),
|
|
|
|
+ now + MIN_TIME_BEFORE_RELOGIN);
|
|
|
|
+ } catch (InterruptedException ie) {
|
|
|
|
+ LOG.warn("Terminating renewal thread");
|
|
|
|
+ return;
|
|
|
|
+ } catch (IOException ie) {
|
|
|
|
+ LOG.warn("Exception encountered while running the" +
|
|
|
|
+ " renewal command. Aborting renew thread. " + ie);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ t.setDaemon(true);
|
|
|
|
+ t.setName("TGT Renewer for " + getUserName());
|
|
|
|
+ t.start();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
/**
|
|
/**
|
|
* Log a user in from a keytab file. Loads a user identity from a keytab
|
|
* Log a user in from a keytab file. Loads a user identity from a keytab
|
|
* file and login them in. They become the currently logged-in user.
|
|
* file and login them in. They become the currently logged-in user.
|
|
@@ -444,6 +537,7 @@ public class UserGroupInformation {
|
|
login.login();
|
|
login.login();
|
|
loginUser = new UserGroupInformation(subject);
|
|
loginUser = new UserGroupInformation(subject);
|
|
loginUser.setLogin(login);
|
|
loginUser.setLogin(login);
|
|
|
|
+ loginUser.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
|
|
} catch (LoginException le) {
|
|
} catch (LoginException le) {
|
|
throw new IOException("Login failure for " + user + " from keytab " +
|
|
throw new IOException("Login failure for " + user + " from keytab " +
|
|
path, le);
|
|
path, le);
|
|
@@ -463,21 +557,20 @@ public class UserGroupInformation {
|
|
*/
|
|
*/
|
|
public synchronized void reloginFromKeytab()
|
|
public synchronized void reloginFromKeytab()
|
|
throws IOException {
|
|
throws IOException {
|
|
- if (!isSecurityEnabled())
|
|
|
|
|
|
+ if (!isSecurityEnabled() ||
|
|
|
|
+ user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS ||
|
|
|
|
+ !isKeytab)
|
|
return;
|
|
return;
|
|
LoginContext login = getLogin();
|
|
LoginContext login = getLogin();
|
|
if (login == null || keytabFile == null) {
|
|
if (login == null || keytabFile == null) {
|
|
throw new IOException("loginUserFromKeyTab must be done first");
|
|
throw new IOException("loginUserFromKeyTab must be done first");
|
|
}
|
|
}
|
|
long now = System.currentTimeMillis();
|
|
long now = System.currentTimeMillis();
|
|
- if (now - lastReloginTime < MIN_TIME_BEFORE_RELOGIN ) {
|
|
|
|
- LOG.warn("Not attempting to re-login since the last re-login was " +
|
|
|
|
- "attempted less than " + (MIN_TIME_BEFORE_RELOGIN/1000) + " seconds"+
|
|
|
|
- " before.");
|
|
|
|
|
|
+ if (!hasSufficientTimeElapsed(now)) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- // register most recent relogin
|
|
|
|
- lastReloginTime = System.currentTimeMillis();
|
|
|
|
|
|
+ // register most recent relogin attempt
|
|
|
|
+ user.setLastLogin(now);
|
|
try {
|
|
try {
|
|
LOG.info("Initiating logout for " + getUserName());
|
|
LOG.info("Initiating logout for " + getUserName());
|
|
//clear up the kerberos state. But the tokens are not cleared! As per
|
|
//clear up the kerberos state. But the tokens are not cleared! As per
|
|
@@ -498,6 +591,49 @@ public class UserGroupInformation {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * Re-Login a user in from the ticket cache. This
|
|
|
|
+ * method assumes that login had happened already.
|
|
|
|
+ * The Subject field of this UserGroupInformation object is updated to have
|
|
|
|
+ * the new credentials.
|
|
|
|
+ * @throws IOException on a failure
|
|
|
|
+ */
|
|
|
|
+ public synchronized void reloginFromTicketCache()
|
|
|
|
+ throws IOException {
|
|
|
|
+ if (!isSecurityEnabled() ||
|
|
|
|
+ user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS ||
|
|
|
|
+ isKeytab)
|
|
|
|
+ return;
|
|
|
|
+ LoginContext login = getLogin();
|
|
|
|
+ if (login == null) {
|
|
|
|
+ throw new IOException("login must be done first");
|
|
|
|
+ }
|
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
|
+ if (!hasSufficientTimeElapsed(now)) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // register most recent relogin attempt
|
|
|
|
+ user.setLastLogin(now);
|
|
|
|
+ try {
|
|
|
|
+ LOG.info("Initiating logout for " + getUserName());
|
|
|
|
+ //clear up the kerberos state. But the tokens are not cleared! As per
|
|
|
|
+ //the Java kerberos login module code, only the kerberos credentials
|
|
|
|
+ //are cleared
|
|
|
|
+ login.logout();
|
|
|
|
+ //login and also update the subject field of this instance to
|
|
|
|
+ //have the new credentials (pass it to the LoginContext constructor)
|
|
|
|
+ login =
|
|
|
|
+ new LoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
|
|
|
|
+ getSubject());
|
|
|
|
+ LOG.info("Initiating re-login for " + getUserName());
|
|
|
|
+ login.login();
|
|
|
|
+ setLogin(login);
|
|
|
|
+ } catch (LoginException le) {
|
|
|
|
+ throw new IOException("Login failure for " + getUserName(), le);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Log a user in from a keytab file. Loads a user identity from a keytab
|
|
* Log a user in from a keytab file. Loads a user identity from a keytab
|
|
* file and login them in. This new user does not affect the currently
|
|
* file and login them in. This new user does not affect the currently
|
|
@@ -527,6 +663,7 @@ public class UserGroupInformation {
|
|
login.login();
|
|
login.login();
|
|
UserGroupInformation newLoginUser = new UserGroupInformation(subject);
|
|
UserGroupInformation newLoginUser = new UserGroupInformation(subject);
|
|
newLoginUser.setLogin(login);
|
|
newLoginUser.setLogin(login);
|
|
|
|
+ newLoginUser.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
|
|
|
|
|
|
return newLoginUser;
|
|
return newLoginUser;
|
|
} catch (LoginException le) {
|
|
} catch (LoginException le) {
|
|
@@ -538,9 +675,24 @@ public class UserGroupInformation {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private boolean hasSufficientTimeElapsed(long now) {
|
|
|
|
+ if (now - user.getLastLogin() < MIN_TIME_BEFORE_RELOGIN ) {
|
|
|
|
+ LOG.warn("Not attempting to re-login since the last re-login was " +
|
|
|
|
+ "attempted less than " + (MIN_TIME_BEFORE_RELOGIN/1000) + " seconds"+
|
|
|
|
+ " before.");
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Did the login happen via keytab
|
|
|
|
+ * @return true or false
|
|
|
|
+ */
|
|
public synchronized static boolean isLoginKeytabBased() {
|
|
public synchronized static boolean isLoginKeytabBased() {
|
|
- return keytabFile != null;
|
|
|
|
|
|
+ return loginUser.isKeytab;
|
|
}
|
|
}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Create a user from a login name. It is intended to be used for remote
|
|
* 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.
|
|
* users in RPC, since it won't have any credentials.
|
|
@@ -553,7 +705,9 @@ public class UserGroupInformation {
|
|
}
|
|
}
|
|
Subject subject = new Subject();
|
|
Subject subject = new Subject();
|
|
subject.getPrincipals().add(new User(user));
|
|
subject.getPrincipals().add(new User(user));
|
|
- return new UserGroupInformation(subject);
|
|
|
|
|
|
+ UserGroupInformation result = new UserGroupInformation(subject);
|
|
|
|
+ result.setAuthenticationMethod(AuthenticationMethod.SIMPLE);
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -586,9 +740,12 @@ public class UserGroupInformation {
|
|
throw new IllegalArgumentException("Null real user");
|
|
throw new IllegalArgumentException("Null real user");
|
|
}
|
|
}
|
|
Subject subject = new Subject();
|
|
Subject subject = new Subject();
|
|
- subject.getPrincipals().add(new User(user));
|
|
|
|
- subject.getPrincipals().add(new RealUser(realUser));
|
|
|
|
- return new UserGroupInformation(subject);
|
|
|
|
|
|
+ Set<Principal> principals = subject.getPrincipals();
|
|
|
|
+ principals.add(new User(user));
|
|
|
|
+ principals.add(new RealUser(realUser));
|
|
|
|
+ UserGroupInformation result =new UserGroupInformation(subject);
|
|
|
|
+ result.setAuthenticationMethod(AuthenticationMethod.PROXY);
|
|
|
|
+ return result;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -692,10 +849,7 @@ public class UserGroupInformation {
|
|
* @return the user's full principal name.
|
|
* @return the user's full principal name.
|
|
*/
|
|
*/
|
|
public String getUserName() {
|
|
public String getUserName() {
|
|
- for (User p: subject.getPrincipals(User.class)) {
|
|
|
|
- return p.getName();
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
|
|
+ return user.getName();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -782,9 +936,7 @@ public class UserGroupInformation {
|
|
*/
|
|
*/
|
|
public synchronized
|
|
public synchronized
|
|
void setAuthenticationMethod(AuthenticationMethod authMethod) {
|
|
void setAuthenticationMethod(AuthenticationMethod authMethod) {
|
|
- for (User p : subject.getPrincipals(User.class)) {
|
|
|
|
- p.setAuthenticationMethod(authMethod);
|
|
|
|
- }
|
|
|
|
|
|
+ user.setAuthenticationMethod(authMethod);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -793,10 +945,7 @@ public class UserGroupInformation {
|
|
* @return AuthenticationMethod in the subject, null if not present.
|
|
* @return AuthenticationMethod in the subject, null if not present.
|
|
*/
|
|
*/
|
|
public synchronized AuthenticationMethod getAuthenticationMethod() {
|
|
public synchronized AuthenticationMethod getAuthenticationMethod() {
|
|
- for (User p: subject.getPrincipals(User.class)) {
|
|
|
|
- return p.getAuthenticationMethod();
|
|
|
|
- }
|
|
|
|
- return null;
|
|
|
|
|
|
+ return user.getAuthenticationMethod();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -909,6 +1058,8 @@ public class UserGroupInformation {
|
|
UserGroupInformation ugi = getCurrentUser();
|
|
UserGroupInformation ugi = getCurrentUser();
|
|
ugi.print();
|
|
ugi.print();
|
|
System.out.println("UGI: " + ugi);
|
|
System.out.println("UGI: " + ugi);
|
|
|
|
+ System.out.println("Auth method " + ugi.user.getAuthenticationMethod());
|
|
|
|
+ System.out.println("Keytab " + ugi.isKeytab);
|
|
System.out.println("============================================================");
|
|
System.out.println("============================================================");
|
|
|
|
|
|
if (args.length == 2) {
|
|
if (args.length == 2) {
|
|
@@ -916,6 +1067,8 @@ public class UserGroupInformation {
|
|
loginUserFromKeytab(args[0], args[1]);
|
|
loginUserFromKeytab(args[0], args[1]);
|
|
getCurrentUser().print();
|
|
getCurrentUser().print();
|
|
System.out.println("Keytab: " + ugi);
|
|
System.out.println("Keytab: " + ugi);
|
|
|
|
+ System.out.println("Auth method " + loginUser.user.getAuthenticationMethod());
|
|
|
|
+ System.out.println("Keytab " + loginUser.isKeytab);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|