From ed4ae0e3ea7ef5646e8ecc30143929e21b8aaab4 Mon Sep 17 00:00:00 2001
From: Suma Shivaprasad <sumasai.shivaprasad@gmail.com>
Date: Mon, 12 Dec 2016 15:25:31 -0800
Subject: [PATCH] ATLAS-1364 HiveHook : Fix Auth issue with doAs (sumasai)

---
 addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java | 52 +++++++++++++++++++++++++++++++++++++++-------------
 notification/src/main/java/org/apache/atlas/hook/AtlasHook.java           |  9 ++++++++-
 release-log.txt                                                           |  1 +
 3 files changed, 48 insertions(+), 14 deletions(-)

diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
index 91b97f1..cf8851c 100755
--- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
+++ b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java
@@ -36,9 +36,6 @@ import org.apache.hadoop.hive.conf.HiveConf;
 import org.apache.hadoop.hive.metastore.TableType;
 import org.apache.hadoop.hive.metastore.api.Database;
 import org.apache.hadoop.hive.metastore.api.FieldSchema;
-import org.apache.hadoop.hive.ql.QueryPlan;
-import org.apache.hadoop.hive.ql.exec.ExplainTask;
-import org.apache.hadoop.hive.ql.exec.Task;
 import org.apache.hadoop.hive.ql.hooks.*;
 import org.apache.hadoop.hive.ql.hooks.Entity;
 import org.apache.hadoop.hive.ql.hooks.Entity.Type;
@@ -50,6 +47,7 @@ import org.apache.hadoop.hive.ql.metadata.HiveException;
 import org.apache.hadoop.hive.ql.metadata.Partition;
 import org.apache.hadoop.hive.ql.metadata.Table;
 import org.apache.hadoop.hive.ql.plan.HiveOperation;
+import org.apache.hadoop.hive.shims.Utils;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hadoop.util.ShutdownHookManager;
 import org.json.JSONObject;
@@ -59,6 +57,7 @@ import org.slf4j.LoggerFactory;
 
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Date;
@@ -73,6 +72,7 @@ import java.util.SortedMap;
 import java.util.SortedSet;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -170,14 +170,14 @@ public class HiveHook extends AtlasHook implements ExecuteWithHookContext {
     public void run(final HookContext hookContext) throws Exception {
         // clone to avoid concurrent access
         try {
-            final HiveConf conf = new HiveConf(hookContext.getConf());
-
             final HiveEventContext event = new HiveEventContext();
             event.setInputs(hookContext.getInputs());
             event.setOutputs(hookContext.getOutputs());
             event.setHookType(hookContext.getHookType());
-            event.setUgi(hookContext.getUgi());
-            event.setUser(getUser(hookContext.getUserName()));
+
+            final UserGroupInformation ugi = hookContext.getUgi() == null ? Utils.getUGI() : hookContext.getUgi();
+            event.setUgi(ugi);
+            event.setUser(getUser(hookContext.getUserName(), hookContext.getUgi()));
             event.setOperation(OPERATION_MAP.get(hookContext.getOperationName()));
             event.setQueryId(hookContext.getQueryPlan().getQueryId());
             event.setQueryStr(hookContext.getQueryPlan().getQueryStr());
@@ -186,13 +186,31 @@ public class HiveHook extends AtlasHook implements ExecuteWithHookContext {
             event.setLineageInfo(hookContext.getLinfo());
 
             if (executor == null) {
-                fireAndForget(event);
+                collect(event);
+                notifyAsPrivilegedAction(event);
             } else {
                 executor.submit(new Runnable() {
                     @Override
                     public void run() {
                         try {
-                            fireAndForget(event);
+                            ugi.doAs(new PrivilegedExceptionAction<Object>() {
+                                @Override
+                                public Object run() throws Exception {
+                                    collect(event);
+                                    return event;
+                                }
+                            });
+
+                            //Notify as 'hive' service user in Kerberos mode else will default to the current user - doAs mode
+                            UserGroupInformation realUser = ugi.getRealUser();
+                            if (realUser != null) {
+                                LOG.info("Sending notification for event {} as service user {} ", event.getOperation(), realUser.getShortUserName());
+                                realUser.doAs(notifyAsPrivilegedAction(event));
+                            } else {
+                                //Unsecure or without doAs
+                                LOG.info("Sending notification for event {} as current user {} ", event.getOperation(), ugi.getShortUserName());
+                                ugi.doAs(notifyAsPrivilegedAction(event));
+                            }
                         } catch (Throwable e) {
                             LOG.error("Atlas hook failed due to error ", e);
                         }
@@ -204,11 +222,21 @@ public class HiveHook extends AtlasHook implements ExecuteWithHookContext {
         }
     }
 
-    private void fireAndForget(HiveEventContext event) throws Exception {
+    PrivilegedExceptionAction<Object> notifyAsPrivilegedAction(final HiveEventContext event) {
+        return new PrivilegedExceptionAction<Object>() {
+            @Override
+            public Object run() throws Exception {
+                notifyEntities(event.getMessages());
+                return event;
+            }
+        };
+    }
+
+    private void collect(HiveEventContext event) throws Exception {
 
         assert event.getHookType() == HookContext.HookType.POST_EXEC_HOOK : "Non-POST_EXEC_HOOK not supported!";
 
-        LOG.info("Entered Atlas hook for hook type {} operation {}", event.getHookType(), event.getOperation());
+        LOG.info("Entered Atlas hook for hook type {}, operation {} , user {} as {}", event.getHookType(), event.getOperation(), event.getUgi().getRealUser(), event.getUgi().getShortUserName());
 
         HiveMetaStoreBridge dgiBridge = new HiveMetaStoreBridge(atlasProperties, hiveConf);
 
@@ -280,8 +308,6 @@ public class HiveHook extends AtlasHook implements ExecuteWithHookContext {
 
         default:
         }
-
-        notifyEntities(event.getMessages());
     }
 
     private void deleteTable(HiveMetaStoreBridge dgiBridge, HiveEventContext event) {
diff --git a/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java b/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java
index 04ee9c0..5bdd5d3 100644
--- a/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java
+++ b/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java
@@ -189,18 +189,25 @@ public abstract class AtlasHook {
 
     public static String getUser(String userName, UserGroupInformation ugi) {
         if (StringUtils.isNotEmpty(userName)) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Returning userName {} " + userName);
+            }
             return userName;
         }
 
         if (ugi != null && StringUtils.isNotEmpty(ugi.getShortUserName())) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Returning ugi.getShortUserName {} " + userName);
+            }
             return ugi.getShortUserName();
         }
 
         try {
             return UserGroupInformation.getCurrentUser().getShortUserName();
         } catch (IOException e) {
-            LOG.warn("Failed for UserGroupInformation.getCurrentUser()");
+            LOG.warn("Failed for UserGroupInformation.getCurrentUser() ", e);
             return System.getProperty("user.name");
         }
     }
+
 }
diff --git a/release-log.txt b/release-log.txt
index 270ffeb..b8786ad 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,6 +9,7 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
 ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
 
 ALL CHANGES:
+ATLAS-1364 HiveHook : Fix Auth issue with doAs (sumasai)
 ATLAS-1340 Credential Provider utility does not work with fully qualified local/HDFS jceks path (vrathor via svimal2106)
 ATLAS-1363 Upgrade front end maven plugin to 1.0 (sumasai)
 ATLAS-1358 NPE Fix for search filter changes & callAPI related fixes (apoorvnaik via sumasai)
--
libgit2 0.27.1