HADOOP6638. try to relogin in a case of failed RPC connection (expired tgt) only in case the subject is loginUser or proxyUgi.realUser.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@948523 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Boris Shkolnik 2010-05-26 18:29:30 +00:00
parent 73643f4211
commit a7aacdc2d6
3 changed files with 41 additions and 23 deletions

View File

@ -28,8 +28,10 @@ Trunk (unreleased changes)
(Patrick Angeles via cdouglas)
BUG FIXES
HADOOP-6638. try to relogin in a case of failed RPC connection (expired tgt)
only in case the subject is loginUser or proxyUgi.realUser. (boryas)
HADOOP-6781. security audit log shouldn't have exception in it.
HADOOP-6781. security audit log shouldn't have exception in it. (boryas)
HADOOP-6612. Protocols RefreshUserToGroupMappingsProtocol and
RefreshAuthorizationPolicyProtocol will fail with security enabled (boryas)

View File

@ -377,26 +377,34 @@ public class Client {
serverPrincipal);
return saslRpcClient.saslConnect(in2, out2);
} catch (javax.security.sasl.SaslException je) {
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
UserGroupInformation realUser = currentUser.getRealUser();
if (authMethod == AuthMethod.KERBEROS &&
UserGroupInformation.isLoginKeytabBased()) {
//try re-login
UserGroupInformation.getCurrentUser().reloginFromKeytab();
//try setting up the connection again
UserGroupInformation.isLoginKeytabBased() &&
// relogin only in case it is the login user (e.g. JT)
// or superuser (like oozie).
((currentUser != null && currentUser.equals(loginUser)) ||
(realUser != null && realUser.equals(loginUser)))) {
try {
//try re-login
loginUser.reloginFromKeytab();
disposeSasl();
saslRpcClient = new SaslRpcClient(authMethod, token,
serverPrincipal);
return saslRpcClient.saslConnect(in2, out2);
} catch (javax.security.sasl.SaslException jee) {
UserGroupInformation.
setLastUnsuccessfulAuthenticationAttemptTime
(System.currentTimeMillis());
LOG.warn("Couldn't setup connection for " +
UserGroupInformation.getCurrentUser().getUserName() +
loginUser.getUserName() +
" to " + serverPrincipal + " even after relogin.");
throw jee;
} catch (IOException ie) {
ie.initCause(je);
throw ie;
}
} else throw je;
}
throw je;
}
}
/** Connect to the server and set up the I/O streams. It then sends

View File

@ -129,8 +129,6 @@ public class UserGroupInformation {
private static boolean useKerberos;
/** Server-side groups fetching service */
private static Groups groups;
/** The last authentication time */
private static long lastUnsuccessfulAuthenticationAttemptTime;
public static final long MIN_TIME_BEFORE_RELOGIN = 10 * 60 * 1000L;
@ -138,6 +136,9 @@ public class UserGroupInformation {
public static final String 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.
* Must be called before useKerberos or groups is used.
@ -205,7 +206,7 @@ public class UserGroupInformation {
private final Subject subject;
private static LoginContext login;
private LoginContext login;
private static final String OS_LOGIN_MODULE_NAME;
private static final Class<? extends Principal> OS_PRINCIPAL_CLASS;
@ -359,12 +360,18 @@ public class UserGroupInformation {
static UserGroupInformation getLoginUser() throws IOException {
if (loginUser == null) {
try {
Subject subject = new Subject();
loginUser = new UserGroupInformation(subject);
LoginContext login;
if (isSecurityEnabled()) {
login = new LoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME);
login = new LoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
subject);
} else {
login = new LoginContext(HadoopConfiguration.SIMPLE_CONFIG_NAME);
login = new LoginContext(HadoopConfiguration.SIMPLE_CONFIG_NAME,
subject);
}
login.login();
loginUser.login = login;
loginUser = new UserGroupInformation(login.getSubject());
String tokenFile = System.getenv(HADOOP_TOKEN_FILE_LOCATION);
if (tokenFile != null && isSecurityEnabled()) {
@ -393,11 +400,14 @@ public class UserGroupInformation {
keytabFile = path;
keytabPrincipal = user;
Subject subject = new Subject();
LoginContext login;
try {
login =
new LoginContext(HadoopConfiguration.KEYTAB_KERBEROS_CONFIG_NAME);
new LoginContext(HadoopConfiguration.KEYTAB_KERBEROS_CONFIG_NAME, subject);
login.login();
loginUser = new UserGroupInformation(login.getSubject());
loginUser = new UserGroupInformation(subject);
loginUser.login = login;
} catch (LoginException le) {
throw new IOException("Login failure for " + user + " from keytab " +
path, le);
@ -420,13 +430,15 @@ public class UserGroupInformation {
if (login == null || keytabFile == null) {
throw new IOException("loginUserFromKeyTab must be done first");
}
if (System.currentTimeMillis() -lastUnsuccessfulAuthenticationAttemptTime <
MIN_TIME_BEFORE_RELOGIN) {
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.");
return;
}
// register most recent relogin
lastReloginTime = System.currentTimeMillis();
try {
LOG.info("Initiating logout for " + getUserName());
//clear up the kerberos state. But the tokens are not cleared! As per
@ -446,11 +458,7 @@ public class UserGroupInformation {
}
}
public synchronized static void
setLastUnsuccessfulAuthenticationAttemptTime(long time) {
lastUnsuccessfulAuthenticationAttemptTime = time;
}
public synchronized static boolean isLoginKeytabBased() {
return keytabFile != null;
}