HADOOP-17159. Make UGI support forceful relogin from keytab ignoring the last login time (#2245)

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:
sguggilam 2020-08-27 15:21:20 -07:00 committed by GitHub
parent a9f82a11df
commit e645204733
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 5 deletions

View File

@ -1215,15 +1215,37 @@ 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 {
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(true);
}
private synchronized void reloginFromKeytab(boolean ignoreTimeElapsed)
throws IOException {
if (!isSecurityEnabled()
|| user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS
|| !isKeytab) {
@ -1231,7 +1253,8 @@ public synchronized void reloginFromKeytab() throws IOException {
}
long now = Time.now();
if (!shouldRenewImmediatelyForTests && !hasSufficientTimeElapsed(now)) {
if (!shouldRenewImmediatelyForTests && !ignoreTimeElapsed
&& !hasSufficientTimeElapsed(now)) {
return;
}

View File

@ -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
@ -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.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);
}
}