Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,29 @@ public void reloginFromKeytab() throws IOException {
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;
}
Expand All @@ -1247,7 +1269,7 @@ private void reloginFromKeytab(boolean checkTGT) throws IOException {
return;
}
}
relogin(login);
relogin(login, ignoreLastLoginTime);
}

/**
Expand All @@ -1268,25 +1290,27 @@ public void reloginFromTicketCache() throws IOException {
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,42 @@ public void testUGIReLoginFromKeytab() throws Exception {
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");
Expand Down