Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 ignoreTimeElapsed)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add javadoc for this method, OR name ignoreTimeElapsed with ignoreLastLoginTime to make it a bit clearer?

throws IOException {
if (!shouldRelogin() || !isFromKeytab()) {
return;
}
Expand All @@ -1247,7 +1269,7 @@ private void reloginFromKeytab(boolean checkTGT) throws IOException {
return;
}
}
relogin(login);
relogin(login, ignoreTimeElapsed);
}

/**
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 ignoreTimeElapsed)
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, ignoreTimeElapsed);
}
}
}

private void unprotectedRelogin(HadoopLoginContext login) throws IOException {
private void unprotectedRelogin(HadoopLoginContext login,
boolean ignoreTimeElapsed) throws IOException {
assert Thread.holdsLock(login.getSubjectLock());
long now = Time.now();
if (!hasSufficientTimeElapsed(now)) {
if (!hasSufficientTimeElapsed(now) && !ignoreTimeElapsed) {
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