HADOOP-13433 Race in UGI.reloginFromKeytab. Contributed by Duo Zhang.
This commit is contained in:
parent
af65f8bb59
commit
04076e783b
|
@ -22,6 +22,8 @@ import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_KERBEROS_MIN_S
|
||||||
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS;
|
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS;
|
||||||
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
|
import static org.apache.hadoop.util.PlatformName.IBM_JAVA;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -43,6 +45,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.security.auth.DestroyFailedException;
|
||||||
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.KerberosPrincipal;
|
import javax.security.auth.kerberos.KerberosPrincipal;
|
||||||
|
@ -74,8 +77,6 @@ import org.apache.hadoop.security.token.TokenIdentifier;
|
||||||
import org.apache.hadoop.util.Shell;
|
import org.apache.hadoop.util.Shell;
|
||||||
import org.apache.hadoop.util.StringUtils;
|
import org.apache.hadoop.util.StringUtils;
|
||||||
import org.apache.hadoop.util.Time;
|
import org.apache.hadoop.util.Time;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -1120,6 +1121,36 @@ public class UserGroupInformation {
|
||||||
reloginFromKeytab();
|
reloginFromKeytab();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the first kerberos ticket is not TGT, then remove and destroy it since
|
||||||
|
// the kerberos library of jdk always use the first kerberos ticket as TGT.
|
||||||
|
// See HADOOP-13433 for more details.
|
||||||
|
private void fixKerberosTicketOrder() {
|
||||||
|
Set<Object> creds = getSubject().getPrivateCredentials();
|
||||||
|
synchronized (creds) {
|
||||||
|
for (Iterator<Object> iter = creds.iterator(); iter.hasNext();) {
|
||||||
|
Object cred = iter.next();
|
||||||
|
if (cred instanceof KerberosTicket) {
|
||||||
|
KerberosTicket ticket = (KerberosTicket) cred;
|
||||||
|
if (!ticket.getServer().getName().startsWith("krbtgt")) {
|
||||||
|
LOG.warn("The first kerberos ticket is not TGT"
|
||||||
|
+ "(the server principal is {}), remove and destroy it.",
|
||||||
|
ticket.getServer());
|
||||||
|
iter.remove();
|
||||||
|
try {
|
||||||
|
ticket.destroy();
|
||||||
|
} catch (DestroyFailedException e) {
|
||||||
|
LOG.warn("destroy ticket failed", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.warn("Warning, no kerberos ticket found while attempting to renew" +
|
||||||
|
" ticket");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-Login a user in from a keytab file. Loads a user identity from a keytab
|
* Re-Login a user in from a keytab file. Loads a user identity from a keytab
|
||||||
* file and logs them in. They become the currently logged-in user. This
|
* file and logs them in. They become the currently logged-in user. This
|
||||||
|
@ -1131,12 +1162,12 @@ public class UserGroupInformation {
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public synchronized void reloginFromKeytab()
|
public synchronized void reloginFromKeytab() throws IOException {
|
||||||
throws IOException {
|
if (!isSecurityEnabled()
|
||||||
if (!isSecurityEnabled() ||
|
|| user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS
|
||||||
user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS ||
|
|| !isKeytab) {
|
||||||
!isKeytab)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
long now = Time.now();
|
long now = Time.now();
|
||||||
if (!shouldRenewImmediatelyForTests && !hasSufficientTimeElapsed(now)) {
|
if (!shouldRenewImmediatelyForTests && !hasSufficientTimeElapsed(now)) {
|
||||||
|
@ -1177,6 +1208,7 @@ public class UserGroupInformation {
|
||||||
}
|
}
|
||||||
start = Time.now();
|
start = Time.now();
|
||||||
login.login();
|
login.login();
|
||||||
|
fixKerberosTicketOrder();
|
||||||
metrics.loginSuccess.add(Time.now() - start);
|
metrics.loginSuccess.add(Time.now() - start);
|
||||||
setLogin(login);
|
setLogin(login);
|
||||||
}
|
}
|
||||||
|
@ -1198,12 +1230,12 @@ public class UserGroupInformation {
|
||||||
*/
|
*/
|
||||||
@InterfaceAudience.Public
|
@InterfaceAudience.Public
|
||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public synchronized void reloginFromTicketCache()
|
public synchronized void reloginFromTicketCache() throws IOException {
|
||||||
throws IOException {
|
if (!isSecurityEnabled()
|
||||||
if (!isSecurityEnabled() ||
|
|| user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS
|
||||||
user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS ||
|
|| !isKrbTkt) {
|
||||||
!isKrbTkt)
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
LoginContext login = getLogin();
|
LoginContext login = getLogin();
|
||||||
if (login == null) {
|
if (login == null) {
|
||||||
throw new IOException("login must be done first");
|
throw new IOException("login must be done first");
|
||||||
|
@ -1231,6 +1263,7 @@ public class UserGroupInformation {
|
||||||
LOG.debug("Initiating re-login for " + getUserName());
|
LOG.debug("Initiating re-login for " + getUserName());
|
||||||
}
|
}
|
||||||
login.login();
|
login.login();
|
||||||
|
fixKerberosTicketOrder();
|
||||||
setLogin(login);
|
setLogin(login);
|
||||||
} catch (LoginException le) {
|
} catch (LoginException le) {
|
||||||
throw new IOException("Login failure for " + getUserName() + ": " + le,
|
throw new IOException("Login failure for " + getUserName() + ": " + le,
|
||||||
|
@ -1238,7 +1271,6 @@ public class UserGroupInformation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
|
Loading…
Reference in New Issue