diff --git a/docs/interpreter/jdbc.md b/docs/interpreter/jdbc.md
index 2c1d2f794c6..57bee4dcff4 100644
--- a/docs/interpreter/jdbc.md
+++ b/docs/interpreter/jdbc.md
@@ -171,7 +171,7 @@ There are more JDBC interpreter properties you can specify like below.
| zeppelin.jdbc.auth.kerberos.proxy.enable |
- When auth type is Kerberos, enable/disable Kerberos proxy with the login user to get the connection. Default value is true. |
+ When auth type is Kerberos, enable/disable Kerberos proxy with the login user to get the connection. Default value is true. |
| default.jceks.file |
@@ -202,7 +202,7 @@ To bind the interpreters created in the interpreter setting page, click the gear
-Select(blue) or deselect(white) the interpreter buttons depending on your use cases.
+Select(blue) or deselect(white) the interpreter buttons depending on your use cases.
If you need to use more than one interpreter in the notebook, activate several buttons.
Don't forget to click `Save` button, or you will face `Interpreter *** is not found` error.
@@ -285,7 +285,7 @@ An example settings of interpreter for the two data sources, each of which has i
##### Usage
-Test of execution *precode* for each data source.
+Test of execution *precode* for each data source.
```sql
%jdbc
@@ -480,7 +480,7 @@ Here are some examples you can refer to. Including the below connectors, you can
[Maven Repository: com.amazonaws:aws-java-sdk-redshift](https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-redshift)
-### Apache Hive
+### Apache Hive
@@ -507,12 +507,11 @@ Here are some examples you can refer to. Including the below connectors, you can
hive_password |
- | hive.proxy.user |
- true or false |
+ default.proxy.user.property |
+ Example value: hive.server2.proxy.user |
+
-Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user` property (set to true by default)
-
[Apache Hive 1 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
[Apache Hive 2 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
@@ -534,6 +533,26 @@ Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user`
[Maven Repository : org.apache.hive:hive-jdbc](https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc)
+##### Impersonation
+When Zeppelin server is running with authentication enabled, then the interpreter can utilize Hive's user proxy feature i.e. send extra parameter for creating and running a session ("hive.server2.proxy.user=": "${loggedInUser}"). This is particularly useful when multiple users are sharing a notebooks.
+
+To enable this set following:
+ - `zeppelin.jdbc.auth.type` as `SIMPLE` or `KERBEROS` (if required) in the interpreter setting.
+ - `${prefix}.proxy.user.property` as `hive.server2.proxy.user`
+ Example configuration
+
+ *Properties*
+
+ | name | value |
+ |:------------------------- |:--------------------------------------------------------------------------------------------------|
+ | hive.driver | org.apache.hive.jdbc.HiveDriver |
+ | hive.password | |
+ | hive.url | jdbc:hive2://hive-server-host:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2 |
+ | hive.proxy.user.property | hive.proxy.user.property |
+ | zeppelin.jdbc.auth.type | SIMPLE |
+
+
+
### Apache Phoenix
Phoenix supports `thick` and `thin` connection types:
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
index cc2c55b0abf..e4040296b2d 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
@@ -26,7 +26,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -179,10 +178,6 @@ public void open() {
}
logger.debug("JDBC PropretiesMap: {}", basePropretiesMap);
- if (!isEmpty(property.getProperty("zeppelin.jdbc.auth.type"))) {
- JDBCSecurityImpl.createSecureConfiguration(property);
- }
-
setMaxLineResults();
}
@@ -358,36 +353,25 @@ public Connection getConnection(String propertyKey, InterpreterContext interpret
} else {
UserGroupInformation.AuthenticationMethod authType = JDBCSecurityImpl.getAuthtype(property);
+ final String connectionUrl = appendProxyUserToURL(url, user, propertyKey);
+
+ JDBCSecurityImpl.createSecureConfiguration(property, authType);
switch (authType) {
case KERBEROS:
if (user == null || "false".equalsIgnoreCase(
- property.getProperty("zeppelin.jdbc.auth.kerberos.proxy.enable"))) {
- connection = getConnectionFromPool(url, user, propertyKey, properties);
+ property.getProperty("zeppelin.jdbc.auth.kerberos.proxy.enable"))) {
+ connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
} else {
- if (url.trim().startsWith("jdbc:hive")) {
- StringBuilder connectionUrl = new StringBuilder(url);
- Integer lastIndexOfUrl = connectionUrl.indexOf("?");
- if (lastIndexOfUrl == -1) {
- lastIndexOfUrl = connectionUrl.length();
- }
- boolean hasProxyUser = property.containsKey("hive.proxy.user");
- if (!hasProxyUser || !property.getProperty("hive.proxy.user").equals("false")){
- logger.debug("Using hive proxy user");
- connectionUrl.insert(lastIndexOfUrl, ";hive.server2.proxy.user=" + user + ";");
- }
- connection = getConnectionFromPool(connectionUrl.toString(),
- user, propertyKey, properties);
+ if (basePropretiesMap.get(propertyKey).containsKey("proxy.user.property")) {
+ connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
} else {
UserGroupInformation ugi = null;
try {
ugi = UserGroupInformation.createProxyUser(
- user, UserGroupInformation.getCurrentUser());
+ user, UserGroupInformation.getCurrentUser());
} catch (Exception e) {
logger.error("Error in getCurrentUser", e);
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(e.getMessage()).append("\n");
- stringBuilder.append(e.getCause());
- throw new InterpreterException(stringBuilder.toString());
+ throw new InterpreterException("Error in getCurrentUser", e);
}
final String poolKey = propertyKey;
@@ -395,28 +379,48 @@ public Connection getConnection(String propertyKey, InterpreterContext interpret
connection = ugi.doAs(new PrivilegedExceptionAction() {
@Override
public Connection run() throws Exception {
- return getConnectionFromPool(url, user, poolKey, properties);
+ return getConnectionFromPool(connectionUrl, user, poolKey, properties);
}
});
} catch (Exception e) {
logger.error("Error in doAs", e);
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(e.getMessage()).append("\n");
- stringBuilder.append(e.getCause());
- throw new InterpreterException(stringBuilder.toString());
+ throw new InterpreterException("Error in doAs", e);
}
}
}
break;
default:
- connection = getConnectionFromPool(url, user, propertyKey, properties);
+ connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
}
}
return connection;
}
+ private String appendProxyUserToURL(String url, String user, String propertyKey) {
+ StringBuilder connectionUrl = new StringBuilder(url);
+
+ if (user != null && !user.equals("anonymous") &&
+ basePropretiesMap.get(propertyKey).containsKey("proxy.user.property")) {
+
+ Integer lastIndexOfUrl = connectionUrl.indexOf("?");
+ if (lastIndexOfUrl == -1) {
+ lastIndexOfUrl = connectionUrl.length();
+ }
+ logger.info("Using proxy user as :" + user);
+ logger.info("Using proxy property for user as :" +
+ basePropretiesMap.get(propertyKey).getProperty("proxy.user.property"));
+ connectionUrl.insert(lastIndexOfUrl, ";" +
+ basePropretiesMap.get(propertyKey).getProperty("proxy.user.property") + "=" + user + ";");
+ } else if (user != null && !user.equals("anonymous") && url.contains("hive")) {
+ logger.warn("User impersonation for hive has changed please refer: http://zeppelin.apache" +
+ ".org/docs/latest/interpreter/jdbc.html#apache-hive");
+ }
+
+ return connectionUrl.toString();
+ }
+
private String getPassword(Properties properties) throws IOException {
if (isNotEmpty(properties.getProperty(PASSWORD_KEY))) {
return properties.getProperty(PASSWORD_KEY);
diff --git a/jdbc/src/main/java/org/apache/zeppelin/jdbc/security/JDBCSecurityImpl.java b/jdbc/src/main/java/org/apache/zeppelin/jdbc/security/JDBCSecurityImpl.java
index 32a7990ff2f..25959e1a810 100644
--- a/jdbc/src/main/java/org/apache/zeppelin/jdbc/security/JDBCSecurityImpl.java
+++ b/jdbc/src/main/java/org/apache/zeppelin/jdbc/security/JDBCSecurityImpl.java
@@ -38,9 +38,8 @@ public class JDBCSecurityImpl {
/***
* @param properties
*/
- public static void createSecureConfiguration(Properties properties) {
- AuthenticationMethod authType = getAuthtype(properties);
-
+ public static void createSecureConfiguration(Properties properties,
+ AuthenticationMethod authType) {
switch (authType) {
case KERBEROS:
Configuration conf = new
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterException.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterException.java
index 30c1c0aae08..ebd184ecfbd 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterException.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterException.java
@@ -31,4 +31,8 @@ public InterpreterException(String m) {
super(m);
}
+ public InterpreterException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
}