You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by pr...@apache.org on 2016/06/27 15:46:41 UTC
zeppelin git commit: ZEPPELIN-1037 Enable Kerberos support in Livy
Interpreter
Repository: zeppelin
Updated Branches:
refs/heads/master c06c375e9 -> 4044189de
ZEPPELIN-1037 Enable Kerberos support in Livy Interpreter
### What is this PR for?
This PR is for enabling kerberos support in Livy interpreter. Also introduced two new Livy interpreter properties called keytab and principal to configure.
### What type of PR is it?
Improvement
### Todos
### What is the Jira issue?
ZEPPELIN-1037
### How should this be tested?
Kerberize the Livy server and configure the Livy interpreter with appropriate keytab and principal.
### Questions:
* Does the licenses files need update? no
* Is there breaking changes for older versions? no
* Does this needs documentation? yes
Author: Renjith Kamath <re...@gmail.com>
Closes #1052 from r-kamath/ZEPPELIN-1037 and squashes the following commits:
3bf7269 [Renjith Kamath] ZEPPELIN-1037 Enable Kerberos support in livy
1cc8c4d [Renjith Kamath] ZEPPELIN-1037 Enable Kerberos support in Livy Interpreter
Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/4044189d
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/4044189d
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/4044189d
Branch: refs/heads/master
Commit: 4044189dec42fed80f0d2b09890df8961d4a57f4
Parents: c06c375
Author: Renjith Kamath <re...@gmail.com>
Authored: Tue Jun 21 23:35:14 2016 +0530
Committer: Prabhjyot Singh <pr...@gmail.com>
Committed: Mon Jun 27 21:16:35 2016 +0530
----------------------------------------------------------------------
livy/pom.xml | 11 +++
.../org/apache/zeppelin/livy/LivyHelper.java | 92 +++++++++-----------
.../src/main/resources/interpreter-setting.json | 10 +++
3 files changed, 60 insertions(+), 53 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4044189d/livy/pom.xml
----------------------------------------------------------------------
diff --git a/livy/pom.xml b/livy/pom.xml
index 90f149c..6fa12b9 100644
--- a/livy/pom.xml
+++ b/livy/pom.xml
@@ -96,6 +96,17 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.springframework.security.kerberos</groupId>
+ <artifactId>spring-security-kerberos-client</artifactId>
+ <version>1.0.1.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>4.3.0.RELEASE</version>
+ </dependency>
+
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4044189d/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java
----------------------------------------------------------------------
diff --git a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java
index 8c4ddab..2c66fa9 100644
--- a/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java
+++ b/livy/src/main/java/org/apache/zeppelin/livy/LivyHelper.java
@@ -21,22 +21,20 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.lang3.StringUtils;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.HttpClientBuilder;
+
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.InterpreterUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.kerberos.client.KerberosRestTemplate;
+import org.springframework.web.client.RestTemplate;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.*;
import java.util.Map.Entry;
@@ -69,14 +67,14 @@ public class LivyHelper {
}
String confData = gson.toJson(conf);
+ String user = context.getAuthenticationInfo().getUser();
- String json = executeHTTP(property.getProperty("zeppelin.livy.url") + "/sessions",
- "POST",
+ String json = executeHTTP(property.getProperty("zeppelin.livy.url") + "/sessions", "POST",
"{" +
"\"kind\": \"" + kind + "\", " +
"\"conf\": " + confData + ", " +
- "\"proxyUser\": \"" + context.getAuthenticationInfo().getUser() +
- "\"}",
+ "\"proxyUser\": " + (StringUtils.isEmpty(user) ? null : "\"" + user + "\"") +
+ "}",
context.getParagraphId()
);
@@ -329,66 +327,54 @@ public class LivyHelper {
}
}
+ private RestTemplate getRestTemplate() {
+ String keytabLocation = property.getProperty("zeppelin.livy.keytab");
+ String principal = property.getProperty("zeppelin.livy.principal");
+ if (StringUtils.isNotEmpty(keytabLocation) && StringUtils.isNotEmpty(principal)) {
+ return new KerberosRestTemplate(keytabLocation, principal);
+ }
+ return new RestTemplate();
+ }
+
protected String executeHTTP(String targetURL, String method, String jsonData, String paragraphId)
throws Exception {
- HttpClient client = HttpClientBuilder.create().build();
- HttpResponse response = null;
+ RestTemplate restTemplate = getRestTemplate();
+ HttpHeaders headers = new HttpHeaders();
+ headers.add("Content-Type", "application/json");
+ ResponseEntity<String> response = null;
if (method.equals("POST")) {
- HttpPost request = new HttpPost(targetURL);
- request.addHeader("Content-Type", "application/json");
- StringEntity se = new StringEntity(jsonData);
- request.setEntity(se);
- response = client.execute(request);
- paragraphHttpMap.put(paragraphId, request);
+ HttpEntity<String> entity = new HttpEntity<String>(jsonData, headers);
+ response = restTemplate.exchange(targetURL, HttpMethod.POST, entity, String.class);
+ paragraphHttpMap.put(paragraphId, response);
} else if (method.equals("GET")) {
- HttpGet request = new HttpGet(targetURL);
- request.addHeader("Content-Type", "application/json");
- response = client.execute(request);
- paragraphHttpMap.put(paragraphId, request);
+ HttpEntity<String> entity = new HttpEntity<String>(headers);
+ response = restTemplate.exchange(targetURL, HttpMethod.GET, entity, String.class);
+ paragraphHttpMap.put(paragraphId, response);
} else if (method.equals("DELETE")) {
- HttpDelete request = new HttpDelete(targetURL);
- request.addHeader("Content-Type", "application/json");
- response = client.execute(request);
+ HttpEntity<String> entity = new HttpEntity<String>(headers);
+ response = restTemplate.exchange(targetURL, HttpMethod.DELETE, entity, String.class);
}
-
if (response == null) {
return null;
}
- if (response.getStatusLine().getStatusCode() == 200
- || response.getStatusLine().getStatusCode() == 201
- || response.getStatusLine().getStatusCode() == 404) {
- return getResponse(response);
+ if (response.getStatusCode().value() == 200
+ || response.getStatusCode().value() == 201
+ || response.getStatusCode().value() == 404) {
+ return response.getBody();
} else {
- String responseString = getResponse(response);
+ String responseString = response.getBody();
if (responseString.contains("CreateInteractiveRequest[\\\"master\\\"]")) {
return responseString;
}
LOGGER.error(String.format("Error with %s StatusCode: %s",
- response.getStatusLine().getStatusCode(), responseString));
+ response.getStatusCode().value(), responseString));
throw new Exception(String.format("Error with %s StatusCode: %s",
- response.getStatusLine().getStatusCode(), responseString));
+ response.getStatusCode().value(), responseString));
}
}
- private String getResponse(HttpResponse response) throws Exception {
- BufferedReader rd = new BufferedReader(
- new InputStreamReader(response.getEntity().getContent()));
-
- StringBuffer result = new StringBuffer();
- String line = "";
- while ((line = rd.readLine()) != null) {
- result.append(line);
- }
- return result.toString();
- }
-
public void cancelHTTP(String paragraphId) {
- if (paragraphHttpMap.get(paragraphId).getClass().getName().contains("HttpPost")) {
- ((HttpPost) paragraphHttpMap.get(paragraphId)).abort();
- } else {
- ((HttpGet) paragraphHttpMap.get(paragraphId)).abort();
- }
paragraphHttpMap.put(paragraphId, null);
}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/4044189d/livy/src/main/resources/interpreter-setting.json
----------------------------------------------------------------------
diff --git a/livy/src/main/resources/interpreter-setting.json b/livy/src/main/resources/interpreter-setting.json
index c22e9a7..7ae435f 100644
--- a/livy/src/main/resources/interpreter-setting.json
+++ b/livy/src/main/resources/interpreter-setting.json
@@ -64,6 +64,16 @@
"propertyName": "livy.spark.dynamicAllocation.maxExecutors",
"defaultValue": "",
"description": "Upper bound for the number of executors if dynamic allocation is enabled."
+ },
+ "zeppelin.livy.principal": {
+ "propertyName": "zeppelin.livy.principal",
+ "defaultValue": "",
+ "description": "Kerberos principal to authenticate livy"
+ },
+ "zeppelin.livy.keytab": {
+ "propertyName": "zeppelin.livy.keytab",
+ "defaultValue": "",
+ "description": "Kerberos keytab to authenticate livy"
}
}
},