ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dbhowm...@apache.org
Subject ambari git commit: AMBARI-18769. Proxy user fixes for Hive view 2.0. (Ashwin Rajeev via dipayanb)
Date Fri, 04 Nov 2016 11:57:29 GMT
Repository: ambari
Updated Branches:
  refs/heads/branch-2.4 4692a16bc -> 97ec99673


AMBARI-18769. Proxy user fixes for Hive view 2.0. (Ashwin Rajeev via dipayanb)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/97ec9967
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/97ec9967
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/97ec9967

Branch: refs/heads/branch-2.4
Commit: 97ec996732a1e3d730c24c196f0108c4ec804e10
Parents: 4692a16
Author: Dipayan Bhowmick <dipayan.bhowmick@gmail.com>
Authored: Fri Nov 4 17:25:11 2016 +0530
Committer: Dipayan Bhowmick <dipayan.bhowmick@gmail.com>
Committed: Fri Nov 4 17:27:07 2016 +0530

----------------------------------------------------------------------
 .../apache/ambari/view/hive2/AuthParams.java    | 102 +++++++++++++++++++
 .../ambari/view/hive2/actor/JdbcConnector.java  |  30 +++++-
 .../view/hive2/actor/message/Connect.java       |   5 +-
 .../hive2/internal/HiveConnectionWrapper.java   |  43 ++++++--
 .../resources/browser/ConnectionService.java    |   4 +-
 .../view/hive2/ConnectionFailuresTest.java      |   9 +-
 .../ambari/view/hive2/JobExecutionTest.java     |   6 +-
 7 files changed, 179 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/AuthParams.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/AuthParams.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/AuthParams.java
new file mode 100644
index 0000000..53077e3
--- /dev/null
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/AuthParams.java
@@ -0,0 +1,102 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ambari.view.hive2;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hadoop.security.UserGroupInformation;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Holds session parameters pulled from the
+ * view context
+ */
+public class AuthParams {
+  private static final String HIVE_SESSION_PARAMS = "hive.session.params";
+  private Map<String, String> sessionParams = new HashMap<>();
+  private final ViewContext context;
+
+  public AuthParams(ViewContext context) {
+    sessionParams = parseSessionParams(context.getProperties().get(HIVE_SESSION_PARAMS));
+    this.context = context;
+  }
+
+  /**
+   * Returns a map created by parsing the parameters in view context
+   * @param params session parameters as string
+   * @return parsed session parameters
+   */
+  private Map<String, String> parseSessionParams(String params) {
+    Map<String, String> sessions = new HashMap<>();
+    if (StringUtils.isEmpty(params))
+      return sessions;
+    String[] splits = params.split(";");
+    for (String split : splits) {
+      String[] paramSplit = split.trim().split("=");
+      if ("auth".equals(paramSplit[0]) || "proxyuser".equals(paramSplit[0])) {
+        sessions.put(paramSplit[0], paramSplit[1]);
+      }
+    }
+    return Collections.unmodifiableMap(sessions);
+  }
+
+  /**
+   * Gets the proxy user
+   * @return User and group information
+   * @throws IOException
+   */
+  public UserGroupInformation getProxyUser() throws IOException {
+    UserGroupInformation ugi;
+    String proxyuser = null;
+    if(context.getCluster() != null) {
+      proxyuser = context.getCluster().getConfigurationValue("cluster-env","ambari_principal_name");
+    }
+
+    if(StringUtils.isEmpty(proxyuser)) {
+      if (sessionParams.containsKey("proxyuser")) {
+        ugi = UserGroupInformation.createRemoteUser(sessionParams.get("proxyuser"));
+      } else {
+        ugi = UserGroupInformation.getCurrentUser();
+      }
+    } else {
+      ugi = UserGroupInformation.createRemoteUser(proxyuser);
+    }
+    ugi.setAuthenticationMethod(getAuthenticationMethod());
+    return ugi;
+  }
+
+  /**
+   * Get the Authentication method
+   * @return
+   */
+  private UserGroupInformation.AuthenticationMethod getAuthenticationMethod() {
+    UserGroupInformation.AuthenticationMethod authMethod;
+    if (sessionParams.containsKey("auth") && !StringUtils.isEmpty(sessionParams.get("auth")))
{
+      String authName = sessionParams.get("auth");
+      authMethod = UserGroupInformation.AuthenticationMethod.valueOf(authName.toUpperCase());
+    } else {
+      authMethod = UserGroupInformation.AuthenticationMethod.SIMPLE;
+    }
+    return authMethod;
+  }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/JdbcConnector.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/JdbcConnector.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/JdbcConnector.java
index fcbef81..d6d5d51 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/JdbcConnector.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/JdbcConnector.java
@@ -24,6 +24,7 @@ import akka.actor.PoisonPill;
 import akka.actor.Props;
 import com.google.common.base.Optional;
 import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive2.AuthParams;
 import org.apache.ambari.view.hive2.ConnectionDelegate;
 import org.apache.ambari.view.hive2.actor.message.Connect;
 import org.apache.ambari.view.hive2.actor.message.FetchError;
@@ -78,6 +79,8 @@ public class JdbcConnector extends HiveActor {
 
   private final Logger LOG = LoggerFactory.getLogger(getClass());
 
+  public static final String SUFFIX = "validating the login";
+
   /**
    * Interval for maximum inactivity allowed
    */
@@ -116,6 +119,7 @@ public class JdbcConnector extends HiveActor {
   private final ActorRef parent;
   private ActorRef statementExecutor = null;
   private final HdfsApi hdfsApi;
+  private final AuthParams authParams;
 
   /**
    * true if the actor is currently executing any job.
@@ -153,6 +157,8 @@ public class JdbcConnector extends HiveActor {
     this.storage = storage;
     this.lastActivityTimestamp = System.currentTimeMillis();
     resultSetIterator = null;
+
+    authParams = new AuthParams(viewContext);
     actorConfiguration = new HiveActorConfiguration(viewContext);
   }
 
@@ -383,10 +389,30 @@ public class JdbcConnector extends HiveActor {
     this.failure = new Failure("Cannot connect to hive", ex);
     if (isAsync()) {
       updateJobStatus(jobId.get(), Job.JOB_STATE_ERROR);
+
+      if(ex instanceof ConnectionException){
+        ConnectionException connectionException = (ConnectionException) ex;
+        Throwable cause = connectionException.getCause();
+        if(cause instanceof SQLException){
+          SQLException sqlException = (SQLException) cause;
+          if(isLoginError(sqlException))
+            return;
+        }
+      }
+
     } else {
       sender().tell(new ExecutionFailed("Cannot connect to hive"), ActorRef.noSender());
     }
-    cleanUpWithTermination();
+    // Do not clean up in case of failed authorizations
+    // The failure is bubbled to the user for requesting credentials
+
+    if (!(ex instanceof SQLException) || !((SQLException) ex).getSQLState().equals("AUTHFAIL"))
{
+      cleanUpWithTermination();
+    }
+  }
+
+  private boolean isLoginError(SQLException ce) {
+    return ce.getCause().getMessage().toLowerCase().endsWith(SUFFIX);
   }
 
   private void keepAlive() {
@@ -410,7 +436,7 @@ public class JdbcConnector extends HiveActor {
     executionType = message.getType();
     // check the connectable
     if (connectable == null) {
-      connectable = message.getConnectable();
+      connectable = message.getConnectable(authParams);
     }
     // make the connectable to Hive
     try {

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/message/Connect.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/message/Connect.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/message/Connect.java
index 49ef3df..360125b 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/message/Connect.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/actor/message/Connect.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.view.hive2.actor.message;
 
 import com.google.common.base.Optional;
+import org.apache.ambari.view.hive2.AuthParams;
 import org.apache.ambari.view.hive2.internal.Connectable;
 import org.apache.ambari.view.hive2.internal.HiveConnectionWrapper;
 
@@ -50,8 +51,8 @@ public class Connect {
     this(HiveJob.Type.SYNC, null, username, password, jdbcUrl);
   }
 
-  public Connectable getConnectable(){
-    return new HiveConnectionWrapper(getJdbcUrl(),username,password);
+  public Connectable getConnectable(AuthParams authParams){
+    return new HiveConnectionWrapper(getJdbcUrl(),username,password, authParams);
   }
 
   public String getUsername() {

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/internal/HiveConnectionWrapper.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/internal/HiveConnectionWrapper.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/internal/HiveConnectionWrapper.java
index 3701016..92a8a2c 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/internal/HiveConnectionWrapper.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/internal/HiveConnectionWrapper.java
@@ -20,8 +20,13 @@ package org.apache.ambari.view.hive2.internal;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
+import org.apache.ambari.view.hive2.AuthParams;
+import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.hive.jdbc.HiveConnection;
 
+import java.io.IOException;
+import java.lang.reflect.UndeclaredThrowableException;
+import java.security.PrivilegedExceptionAction;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
@@ -31,24 +36,27 @@ import java.sql.SQLException;
  * This class only provides a connection over which
  * callers should run their own JDBC statements
  */
-public class HiveConnectionWrapper implements Connectable,Supplier<HiveConnection>
{
+public class HiveConnectionWrapper implements Connectable, Supplier<HiveConnection>
{
 
   private static String DRIVER_NAME = "org.apache.hive.jdbc.HiveDriver";
   public static final String SUFFIX = "validating the login";
   private final String jdbcUrl;
   private final String username;
   private final String password;
+  private final AuthParams authParams;
+
+  private UserGroupInformation ugi;
 
   private HiveConnection connection = null;
   private boolean authFailed;
 
-  public HiveConnectionWrapper(String jdbcUrl, String username, String password) {
+  public HiveConnectionWrapper(String jdbcUrl, String username, String password, AuthParams
authParams) {
     this.jdbcUrl = jdbcUrl;
     this.username = username;
     this.password = password;
+    this.authParams = authParams;
   }
 
-
   @Override
   public void connect() throws ConnectionException {
     try {
@@ -58,16 +66,33 @@ public class HiveConnectionWrapper implements Connectable,Supplier<HiveConnectio
     }
 
     try {
-      Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
-      connection = (HiveConnection)conn;
+      ugi = UserGroupInformation.createProxyUser(username, authParams.getProxyUser());
+    } catch (IOException e) {
+      throw new ConnectionException(e, "Cannot set kerberos authentication for getting connection.");
+    }
 
-    } catch (SQLException e) {
-      if(isLoginError(e))
-        this.authFailed = true;
+    try {
+      Connection conn = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
+        @Override
+        public Connection run() throws Exception {
+          return DriverManager.getConnection(jdbcUrl, username, password);
+        }
+      });
+      connection = (HiveConnection) conn;
+    } catch (UndeclaredThrowableException exception) {
+      // Check if the reason was an auth error
+      Throwable undeclaredThrowable = exception.getUndeclaredThrowable();
+      if (undeclaredThrowable instanceof SQLException) {
+        SQLException sqlException = (SQLException) undeclaredThrowable;
+        if (isLoginError(sqlException))
+          authFailed = true;
+        throw new ConnectionException(sqlException, "Cannot open a hive connection with connect
string " + jdbcUrl);
+      }
+
+    } catch (IOException | InterruptedException e) {
       throw new ConnectionException(e, "Cannot open a hive connection with connect string
" + jdbcUrl);
     }
 
-
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/browser/ConnectionService.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/browser/ConnectionService.java
b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/browser/ConnectionService.java
index eb1609d..cd4d30e 100644
--- a/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/browser/ConnectionService.java
+++ b/contrib/views/hive-next/src/main/java/org/apache/ambari/view/hive2/resources/browser/ConnectionService.java
@@ -19,8 +19,8 @@
 package org.apache.ambari.view.hive2.resources.browser;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
 import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.hive2.AuthParams;
 import org.apache.ambari.view.hive2.ConnectionFactory;
 import org.apache.ambari.view.hive2.ConnectionSystem;
 import org.apache.ambari.view.hive2.client.ConnectionConfig;
@@ -97,7 +97,7 @@ public class ConnectionService {
 
     private Response attemptHiveConnection(String pass) {
         ConnectionConfig connectionConfig = ConnectionFactory.create(context);
-        HiveConnectionWrapper hiveConnectionWrapper = new HiveConnectionWrapper(connectionConfig.getJdbcUrl(),
connectionConfig.getUsername(), pass);
+        HiveConnectionWrapper hiveConnectionWrapper = new HiveConnectionWrapper(connectionConfig.getJdbcUrl(),
connectionConfig.getUsername(), pass,new AuthParams(context));
         try {
           hiveConnectionWrapper.connect();
         } catch (ConnectionException e) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/ConnectionFailuresTest.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/ConnectionFailuresTest.java
b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/ConnectionFailuresTest.java
index e36c1d4..7cb2dd7 100644
--- a/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/ConnectionFailuresTest.java
+++ b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/ConnectionFailuresTest.java
@@ -47,6 +47,7 @@ import org.junit.Test;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.HashMap;
 
 import static org.easymock.EasyMock.*;
 
@@ -86,7 +87,8 @@ public class ConnectionFailuresTest {
             Props.create(OperationController.class, actorSystem, deathwatch, viewContext,
connectionSupplier, dataStorageSupplier, hdfsApiSupplier), "operationController-test");
     expect(hdfsApiSupplier.get(viewContext)).andReturn(Optional.of(hdfsApi));
     expect(viewContext.getInstanceName()).andReturn("test").anyTimes();
-    expect(connect.getConnectable()).andReturn(connectionWrapper);
+    expect(viewContext.getProperties()).andReturn(new HashMap<String, String>()).anyTimes();
+    expect(connect.getConnectable(anyObject(AuthParams.class))).andReturn(connectionWrapper);
     expect(connectionWrapper.isOpen()).andReturn(false).anyTimes();
     expect(connectionWrapper.getConnection()).andReturn(Optional.<HiveConnection>absent()).anyTimes();
     expect(dataStorageSupplier.get(viewContext)).andReturn(storage);
@@ -127,7 +129,8 @@ public class ConnectionFailuresTest {
     ActorRef operationControl = actorSystem.actorOf(
             Props.create(OperationController.class, actorSystem, deathwatch, viewContext,
connectionSupplier, dataStorageSupplier, hdfsApiSupplier), "operationController-test");
     expect(hdfsApiSupplier.get(viewContext)).andReturn(Optional.of(hdfsApi));
-    expect(connect.getConnectable()).andReturn(connectionWrapper);
+    expect(viewContext.getProperties()).andReturn(new HashMap<String, String>()).anyTimes();
+    expect(connect.getConnectable(anyObject(AuthParams.class))).andReturn(connectionWrapper);
     expect(connectionWrapper.isOpen()).andReturn(false);
     expect(connectionWrapper.getConnection()).andReturn(Optional.of(hiveConnection)).anyTimes();
     expect(dataStorageSupplier.get(viewContext)).andReturn(storage);
@@ -141,7 +144,7 @@ public class ConnectionFailuresTest {
     connectionWrapper.connect();
     jobImpl.setStatus(Job.JOB_STATE_ERROR);
     storage.store(JobImpl.class, jobImpl);
-    replay(connect, hdfsApiSupplier, dataStorageSupplier, connectionWrapper,
+    replay(viewContext, connect, hdfsApiSupplier, dataStorageSupplier, connectionWrapper,
             storage, jobImpl, connectionSupplier, delegate, statement, resultSet);
 
     operationControl.tell(executeJob, ActorRef.noSender());

http://git-wip-us.apache.org/repos/asf/ambari/blob/97ec9967/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/JobExecutionTest.java
----------------------------------------------------------------------
diff --git a/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/JobExecutionTest.java
b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/JobExecutionTest.java
index fc042ce..f8e88a4 100644
--- a/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/JobExecutionTest.java
+++ b/contrib/views/hive-next/src/test/java/org/apache/ambari/view/hive2/JobExecutionTest.java
@@ -47,6 +47,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.sql.ResultSet;
+import java.util.HashMap;
 
 import static org.easymock.EasyMock.*;
 
@@ -85,7 +86,8 @@ public class JobExecutionTest {
     ActorRef operationControl = actorSystem.actorOf(
             Props.create(OperationController.class, actorSystem, deathwatch, viewContext,
connectionSupplier, dataStorageSupplier, hdfsApiSupplier), "operationController-test");
     expect(hdfsApiSupplier.get(viewContext)).andReturn(Optional.of(hdfsApi));
-    expect(connect.getConnectable()).andReturn(connectionWrapper);
+    expect(viewContext.getProperties()).andReturn(new HashMap<String, String>()).anyTimes();
+    expect(connect.getConnectable(anyObject(AuthParams.class))).andReturn(connectionWrapper);
     expect(connectionWrapper.isOpen()).andReturn(false);
     expect(connectionWrapper.getConnection()).andReturn(Optional.of(hiveConnection)).anyTimes();
     expect(dataStorageSupplier.get(viewContext)).andReturn(storage);
@@ -100,7 +102,7 @@ public class JobExecutionTest {
     connectionWrapper.connect();
     jobImpl.setStatus(Job.JOB_STATE_FINISHED);
     storage.store(JobImpl.class, jobImpl);
-    replay(connect, hdfsApiSupplier, dataStorageSupplier, connectionWrapper,
+    replay(viewContext, connect, hdfsApiSupplier, dataStorageSupplier, connectionWrapper,
             storage, jobImpl, connectionSupplier, delegate, statement, resultSet);
 
     operationControl.tell(executeJob, ActorRef.noSender());


Mime
View raw message