Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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 @@ -1215,23 +1215,43 @@ private void fixKerberosTicketOrder() {
* 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
* method assumes that {@link #loginUserFromKeytab(String, String)} had
* happened already.
* The Subject field of this UserGroupInformation object is updated to have
* the new credentials.
* 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 synchronized void reloginFromKeytab() throws IOException {
reloginFromKeytab(false);
}

/**
* Force 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 method assumes that {@link #loginUserFromKeytab(String, String)} had
* happened already. The Subject field of this UserGroupInformation object is
* updated to have the new credentials.
*
* @param ignoreTimeElapsed Force re-login irrespective of the time of last
* login
* @throws IOException
* @throws KerberosAuthException on a failure
*/
@InterfaceAudience.Public
@InterfaceStability.Evolving
public synchronized void reloginFromKeytab(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.

I'm thinking of the same problem of the same method signature when potential Hadoop 2 code calling reloginFromKeytab(false) upgrades to Hadoop 3. Because of the same method name and a bool parameter, users most likely will not notice the parameter value is for different meanings: in Hadoop 2 here, the bool parameter is for ignoreTimeElapsed where in Hadoop 3 it is actually for checkTGT.

So is it better to:

  1. Make this new API public synchronized void reloginFromKeytab(boolean ignoreTimeElapsed) private
  2. AND we also add the new API as in Hadoop 3: public void forceReloginFromKeytab().

That way, the application code which forces login will have the same code between Hadoop 2 and 3. And the other new API reloginFromKeytab(boolean) is private in UGI both in Hadoop 2 and 3.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@liuml07 Yes it makes sense to keep the code consistent for the callers to avoid such issues with a upgrade

throws IOException {
if (!isSecurityEnabled()
|| user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS
|| !isKeytab) {
return;
}

long now = Time.now();
if (!shouldRenewImmediatelyForTests && !hasSufficientTimeElapsed(now)) {
if (!shouldRenewImmediatelyForTests && !ignoreTimeElapsed
&& !hasSufficientTimeElapsed(now)) {
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

import java.io.File;

import javax.security.auth.login.LoginContext;

/**
* Verify UGI login from keytab. Check that the UGI is
* configured to use keytab to catch regressions like
Expand Down Expand Up @@ -115,4 +117,39 @@ public void testUGIReloginFromKeytab() throws Exception {
secondLogin > firstLogin);
}

/**
* 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 {
UserGroupInformation.setShouldRenewImmediatelyForTests(true);
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 = ugi.getSubject().getPrincipals(User.class).iterator().next();
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.reloginFromKeytab(true);
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);
}

}