ACCUMULO-4070 Backport server-side fix Kerberos renewal from ACCUMULO-4069

Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/4d952ac0
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/4d952ac0
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/4d952ac0

Branch: refs/heads/master
Commit: 4d952ac070c399cd16688eefd5d8a5c3f80e753c
Parents: bd8cf5e
Author: Josh Elser <els...@apache.org>
Authored: Thu Dec 3 01:53:27 2015 -0500
Committer: Josh Elser <els...@apache.org>
Committed: Thu Dec 3 16:20:56 2015 -0500

----------------------------------------------------------------------
 .../org/apache/accumulo/core/conf/Property.java |  2 +
 .../accumulo/server/security/SecurityUtil.java  | 47 ++++++++++++++++++--
 2 files changed, 45 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/accumulo/blob/4d952ac0/core/src/main/java/org/apache/accumulo/core/conf/Property.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/accumulo/core/conf/Property.java 
b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
index 6d1f043..632bb59 100644
--- a/core/src/main/java/org/apache/accumulo/core/conf/Property.java
+++ b/core/src/main/java/org/apache/accumulo/core/conf/Property.java
@@ -160,6 +160,8 @@ public enum Property {
   GENERAL_KERBEROS_KEYTAB("general.kerberos.keytab", "", PropertyType.PATH, 
"Path to the kerberos keytab to use. Leave blank if not using kerberoized 
hdfs"),
   GENERAL_KERBEROS_PRINCIPAL("general.kerberos.principal", "", 
PropertyType.STRING, "Name of the kerberos principal to use. _HOST will 
automatically be "
       + "replaced by the machines hostname in the hostname portion of the 
principal. Leave blank if not using kerberoized hdfs"),
+  GENERAL_KERBEROS_RENEWAL_PERIOD("general.kerberos.renewal.period", "30s", 
PropertyType.TIMEDURATION, "The amount of time between attempts to perform "
+      + "Kerberos ticket renewals. This does not equate to how often tickets 
are actually renewed (which is performed at 80% of the ticket lifetime)."),
   GENERAL_MAX_MESSAGE_SIZE("general.server.message.size.max", "1G", 
PropertyType.MEMORY, "The maximum size of a message that can be sent to a 
server."),
   @Experimental
   GENERAL_VOLUME_CHOOSER("general.volume.chooser", 
"org.apache.accumulo.server.fs.RandomVolumeChooser", PropertyType.CLASSNAME,

http://git-wip-us.apache.org/repos/asf/accumulo/blob/4d952ac0/server/base/src/main/java/org/apache/accumulo/server/security/SecurityUtil.java
----------------------------------------------------------------------
diff --git 
a/server/base/src/main/java/org/apache/accumulo/server/security/SecurityUtil.java
 
b/server/base/src/main/java/org/apache/accumulo/server/security/SecurityUtil.java
index 42d1313..9e0eb04 100644
--- 
a/server/base/src/main/java/org/apache/accumulo/server/security/SecurityUtil.java
+++ 
b/server/base/src/main/java/org/apache/accumulo/server/security/SecurityUtil.java
@@ -21,6 +21,8 @@ import java.net.InetAddress;
 
 import org.apache.accumulo.core.conf.AccumuloConfiguration;
 import org.apache.accumulo.core.conf.Property;
+import org.apache.accumulo.core.util.Daemon;
+import org.apache.accumulo.fate.util.LoggingRunnable;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.log4j.Logger;
 
@@ -29,6 +31,7 @@ import org.apache.log4j.Logger;
  */
 public class SecurityUtil {
   private static final Logger log = Logger.getLogger(SecurityUtil.class);
+  private static final Logger renewalLog = 
Logger.getLogger("KerberosTicketRenewal");
   public static boolean usingKerberos = false;
 
   /**
@@ -48,11 +51,10 @@ public class SecurityUtil {
 
     if (login(principalConfig, keyTab)) {
       try {
-        // This spawns a thread to periodically renew the logged in (accumulo) 
user
-        UserGroupInformation.getLoginUser();
+        startTicketRenewalThread(UserGroupInformation.getCurrentUser(), 
acuConf.getTimeInMillis(Property.GENERAL_KERBEROS_RENEWAL_PERIOD));
         return;
-      } catch (IOException io) {
-        log.error("Error starting up renewal thread. This shouldn't be 
happenining.", io);
+      } catch (IOException e) {
+        log.error("Failed to obtain Kerberos user after successfully logging 
in", e);
       }
     }
 
@@ -80,4 +82,41 @@ public class SecurityUtil {
     }
     return false;
   }
+
+  /**
+   * Start a thread that periodically attempts to renew the current Kerberos 
user's ticket.
+   *
+   * @param ugi
+   *          The current Kerberos user.
+   * @param renewalPeriod
+   *          The amount of time between attempting renewals.
+   */
+  static void startTicketRenewalThread(final UserGroupInformation ugi, final 
long renewalPeriod) {
+    Thread t = new Daemon(new LoggingRunnable(renewalLog, new Runnable() {
+      @Override
+      public void run() {
+        while (true) {
+          try {
+            renewalLog.debug("Invoking renewal attempt for Kerberos ticket");
+            // While we run this "frequently", the Hadoop implementation will 
only perform the login at 80% of ticket lifetime.
+            ugi.checkTGTAndReloginFromKeytab();
+          } catch (IOException e) {
+            // Should failures to renew the ticket be retried more quickly?
+            renewalLog.error("Failed to renew Kerberos ticket", e);
+          }
+
+          // Wait for a bit before checking again.
+          try {
+            Thread.sleep(renewalPeriod);
+          } catch (InterruptedException e) {
+            renewalLog.error("Renewal thread interrupted", e);
+            Thread.currentThread().interrupt();
+            return;
+          }
+        }
+      }
+    }));
+    t.setName("Kerberos Ticket Renewal");
+    t.start();
+  }
 }

Reply via email to