From a5c8c616ed2332a2d2510f50cf1e64a347f1fba8 Mon Sep 17 00:00:00 2001 From: Sandeep Guggilam Date: Tue, 25 Aug 2020 08:14:55 -0700 Subject: [PATCH 1/3] HADOOP-17159 Ability for forceful relogin in UserGroupInformation class --- .../hadoop/security/UserGroupInformation.java | 28 ++++++++++++-- .../security/TestUGILoginFromKeytab.java | 37 +++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java index 07cd31496cd33..9aca0e67d45f1 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java @@ -1215,15 +1215,34 @@ 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) + throws IOException { if (!isSecurityEnabled() || user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS || !isKeytab) { @@ -1231,7 +1250,8 @@ public synchronized void reloginFromKeytab() throws IOException { } long now = Time.now(); - if (!shouldRenewImmediatelyForTests && !hasSufficientTimeElapsed(now)) { + if (!shouldRenewImmediatelyForTests && !ignoreTimeElapsed + && !hasSufficientTimeElapsed(now)) { return; } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java index 66c2af46d1097..49e24e1d59427 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java @@ -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.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); + } + } From 23654b10dd8ac71a1bd01c05b60f2b24011aaebe Mon Sep 17 00:00:00 2001 From: Sandeep Guggilam Date: Tue, 25 Aug 2020 11:36:41 -0700 Subject: [PATCH 2/3] Fix checkstyle warnings --- .../java/org/apache/hadoop/security/UserGroupInformation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java index 9aca0e67d45f1..71ea13a83838a 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java @@ -1217,7 +1217,7 @@ private void fixKerberosTicketOrder() { * 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 */ @@ -1233,7 +1233,7 @@ public synchronized void reloginFromKeytab() throws IOException { * 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 From 40c83137f15e11c3ee394b7794b8e5bd80182cef Mon Sep 17 00:00:00 2001 From: Sandeep Guggilam Date: Thu, 27 Aug 2020 12:44:04 -0700 Subject: [PATCH 3/3] Add a new API forceRelogin --- .../hadoop/security/UserGroupInformation.java | 21 +++++++++++-------- .../security/TestUGILoginFromKeytab.java | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java index 71ea13a83838a..bc8b47a509fc5 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java @@ -1223,25 +1223,28 @@ private void fixKerberosTicketOrder() { */ @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. 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. + * 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. * - * @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) + public void forceReloginFromKeytab() throws IOException { + reloginFromKeytab(true); + } + + private synchronized void reloginFromKeytab(boolean ignoreTimeElapsed) throws IOException { if (!isSecurityEnabled() || user.getAuthenticationMethod() != AuthenticationMethod.KERBEROS diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java index 49e24e1d59427..0ada333248a48 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUGILoginFromKeytab.java @@ -143,7 +143,7 @@ public void testUGIForceReLoginFromKeytab() throws Exception { Thread.sleep(2000); // Force relogin from keytab - ugi.reloginFromKeytab(true); + ugi.forceReloginFromKeytab(); final long secondLogin = user.getLastLogin(); final LoginContext login2 = user.getLogin(); Assert.assertTrue("User should have been able to relogin from keytab",