HADOOP-17159. Make UGI support forceful relogin from keytab ignoring the last login time (#2249)
Contributed by Sandeep Guggilam. Signed-off-by: Mingliang Liu <liuml07@apache.org> Signed-off-by: Steve Loughran <stevel@apache.org>
This commit is contained in:
parent
9f94c9e60d
commit
e1ac832d5d
|
@ -1115,7 +1115,29 @@ public class UserGroupInformation {
|
|||
reloginFromKeytab(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force re-Login a user in from a keytab file irrespective of the last login
|
||||
* time. Loads a user identity from a keytab file and logs them in. They
|
||||
* become the currently logged-in user. This method assumes that
|
||||
* {@link #loginUserFromKeytab(String, String)} had happened already. The
|
||||
* Subject field of this UserGroupInformation object is updated to have the
|
||||
* new credentials.
|
||||
*
|
||||
* @throws IOException
|
||||
* @throws KerberosAuthException on a failure
|
||||
*/
|
||||
@InterfaceAudience.Public
|
||||
@InterfaceStability.Evolving
|
||||
public void forceReloginFromKeytab() throws IOException {
|
||||
reloginFromKeytab(false, true);
|
||||
}
|
||||
|
||||
private void reloginFromKeytab(boolean checkTGT) throws IOException {
|
||||
reloginFromKeytab(checkTGT, false);
|
||||
}
|
||||
|
||||
private void reloginFromKeytab(boolean checkTGT, boolean ignoreLastLoginTime)
|
||||
throws IOException {
|
||||
if (!shouldRelogin() || !isFromKeytab()) {
|
||||
return;
|
||||
}
|
||||
|
@ -1130,7 +1152,7 @@ public class UserGroupInformation {
|
|||
return;
|
||||
}
|
||||
}
|
||||
relogin(login);
|
||||
relogin(login, ignoreLastLoginTime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1151,25 +1173,27 @@ public class UserGroupInformation {
|
|||
if (login == null) {
|
||||
throw new KerberosAuthException(MUST_FIRST_LOGIN);
|
||||
}
|
||||
relogin(login);
|
||||
relogin(login, false);
|
||||
}
|
||||
|
||||
private void relogin(HadoopLoginContext login) throws IOException {
|
||||
private void relogin(HadoopLoginContext login, boolean ignoreLastLoginTime)
|
||||
throws IOException {
|
||||
// ensure the relogin is atomic to avoid leaving credentials in an
|
||||
// inconsistent state. prevents other ugi instances, SASL, and SPNEGO
|
||||
// from accessing or altering credentials during the relogin.
|
||||
synchronized(login.getSubjectLock()) {
|
||||
// another racing thread may have beat us to the relogin.
|
||||
if (login == getLogin()) {
|
||||
unprotectedRelogin(login);
|
||||
unprotectedRelogin(login, ignoreLastLoginTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unprotectedRelogin(HadoopLoginContext login) throws IOException {
|
||||
private void unprotectedRelogin(HadoopLoginContext login,
|
||||
boolean ignoreLastLoginTime) throws IOException {
|
||||
assert Thread.holdsLock(login.getSubjectLock());
|
||||
long now = Time.now();
|
||||
if (!hasSufficientTimeElapsed(now)) {
|
||||
if (!hasSufficientTimeElapsed(now) && !ignoreLastLoginTime) {
|
||||
return;
|
||||
}
|
||||
// register most recent relogin attempt
|
||||
|
|
|
@ -154,6 +154,42 @@ public class TestUGILoginFromKeytab {
|
|||
Assert.assertNotSame(login1, login2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force re-login from keytab using the MiniKDC and verify the UGI can
|
||||
* successfully relogin from keytab as well.
|
||||
*/
|
||||
@Test
|
||||
public void testUGIForceReLoginFromKeytab() throws Exception {
|
||||
// Set this to false as we are testing force re-login anyways
|
||||
UserGroupInformation.setShouldRenewImmediatelyForTests(false);
|
||||
String principal = "foo";
|
||||
File keytab = new File(workDir, "foo.keytab");
|
||||
kdc.createPrincipal(keytab, principal);
|
||||
|
||||
UserGroupInformation.loginUserFromKeytab(principal, keytab.getPath());
|
||||
UserGroupInformation ugi = UserGroupInformation.getLoginUser();
|
||||
Assert.assertTrue("UGI should be configured to login from keytab",
|
||||
ugi.isFromKeytab());
|
||||
|
||||
// Verify relogin from keytab.
|
||||
User user = getUser(ugi.getSubject());
|
||||
final long firstLogin = user.getLastLogin();
|
||||
final LoginContext login1 = user.getLogin();
|
||||
Assert.assertNotNull(login1);
|
||||
|
||||
// Sleep for 2 secs to have a difference between first and second login
|
||||
Thread.sleep(2000);
|
||||
|
||||
// Force relogin from keytab
|
||||
ugi.forceReloginFromKeytab();
|
||||
final long secondLogin = user.getLastLogin();
|
||||
final LoginContext login2 = user.getLogin();
|
||||
Assert.assertTrue("User should have been able to relogin from keytab",
|
||||
secondLogin > firstLogin);
|
||||
Assert.assertNotNull(login2);
|
||||
Assert.assertNotSame(login1, login2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUGIFromKnownSubject() throws Exception {
|
||||
KerberosPrincipal principal = new KerberosPrincipal("user");
|
||||
|
|
Loading…
Reference in New Issue