Skip to content
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions docs/interpreter/jdbc.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,6 @@ There are more JDBC interpreter properties you can specify like below.
<td>zeppelin.jdbc.keytab.location</td>
<td>The path to the keytab file</td>
</tr>
<tr>
<td>zeppelin.jdbc.auth.kerberos.proxy.enable</td>
     <td>When auth type is Kerberos, enable/disable Kerberos proxy with the login user to get the connection. Default value is true.</td>
</tr>
<tr>
<td>default.jceks.file</td>
<td>jceks store path (e.g: jceks://file/tmp/zeppelin.jceks)</td>
Expand Down Expand Up @@ -202,7 +198,7 @@ To bind the interpreters created in the interpreter setting page, click the gear

<img src="../assets/themes/zeppelin/img/docs-img/click_interpreter_binding_button.png" width="600px" />

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.

Expand Down Expand Up @@ -285,7 +281,7 @@ An example settings of interpreter for the two data sources, each of which has i
</table>

##### Usage
Test of execution *precode* for each data source.
Test of execution *precode* for each data source.

```sql
%jdbc
Expand Down Expand Up @@ -480,7 +476,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

<img src="../assets/themes/zeppelin/img/docs-img/hive_setting.png" width="600px" />

Expand All @@ -507,8 +503,9 @@ Here are some examples you can refer to. Including the below connectors, you can
<td>hive_password</td>
</tr>
<tr>
<td>hive.proxy.user</td>
<td>true or false</td>
<td>default.proxy.user.property</td>
<td>hive.server2.proxy.user</td>
</tr>
</table>

Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user` property (set to true by default)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is hive.proxy.user removed then? do we need to doc to explain the migration?
also you have this line here still with hive.proxy.user property (set to true by default)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the preference would be to have a way to migrate existing users and config by having it automatically converted, add a log warning etc.

but it's your call in the specific case

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant in above line was the key is default.proxy.user.property with an example value hive.server2.proxy.user; fair point, let me tweak this documentation.

Yes, adding a log (logger.warn) does make sense, let me do it right away.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was looking at http://zeppelin.apache.org/docs/0.7.1/interpreter/jdbc.html#apache-hive, hive.proxy.user hasn't made it to the doc section, so I think in this case no need to add migration steps. However, I have added logger.warn as well.

Expand All @@ -534,6 +531,14 @@ 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.
- `default.proxy.user.property` as `hive.server2.proxy.user`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we clarify, default here could also be the name of the hive interpreter instance like hive.proxy.user.property?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, let me change this to {propertyKey}.proxy.user.property and post a sample configuration.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for reviewing this. Have handled your review comments.



### Apache Phoenix

Phoenix supports `thick` and `thin` connection types:
Expand Down
100 changes: 50 additions & 50 deletions jdbc/src/main/java/org/apache/zeppelin/jdbc/JDBCInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -179,10 +178,6 @@ public void open() {
}
logger.debug("JDBC PropretiesMap: {}", basePropretiesMap);

if (!isEmpty(property.getProperty("zeppelin.jdbc.auth.type"))) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also removed? zeppelin.jdbc.auth.type?

@prabhjyotsingh prabhjyotsingh Apr 29, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JDBCSecurityImpl.createSecureConfiguration call is moved to line#358 (https://github.com/apache/zeppelin/pull/2229/files/9fee9d2a9e476769b5d28a50d17f3a7ad38fc453#diff-ecdae8ee9594a5c4b21a3c217a3f130cR358). Instead of making this object JDBCSecurityImpl.getAuthtype(property) every time on open() do it only if required.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ok, doc change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's just a removal of extra call, so no doc change required.

JDBCSecurityImpl.createSecureConfiguration(property);
}

setMaxLineResults();
}

Expand Down Expand Up @@ -358,65 +353,70 @@ 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);
if (url.trim().startsWith("jdbc:hive")) {
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);
} else {
UserGroupInformation ugi = null;
try {
ugi = UserGroupInformation.createProxyUser(
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());
}

final String poolKey = propertyKey;
try {
connection = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
@Override
public Connection run() throws Exception {
return getConnectionFromPool(url, 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());
}
UserGroupInformation ugi = null;
try {
ugi = UserGroupInformation.createProxyUser(
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());
}

final String poolKey = propertyKey;
try {
connection = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
@Override
public Connection run() throws Exception {
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());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just include e as inner exception like InterpreterException(message, e)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure just did it, thank you for the hint.

}
}
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 hive proxy user as :" + user);
connectionUrl.insert(lastIndexOfUrl, ";" +
basePropretiesMap.get(propertyKey).getProperty("proxy.user.property") + "=" + user + ";");
}

return connectionUrl.toString();
}

private String getPassword(Properties properties) throws IOException {
if (isNotEmpty(properties.getProperty(PASSWORD_KEY))) {
return properties.getProperty(PASSWORD_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down