diff --git a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java
index 597fa1e..5f9d985 100644
--- a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java
+++ b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java
@@ -18,6 +18,13 @@
package org.apache.hive.jdbc;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
import java.sql.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
@@ -44,6 +51,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslException;
@@ -60,7 +68,11 @@
import org.apache.hive.service.cli.thrift.TOpenSessionResp;
import org.apache.hive.service.cli.thrift.TProtocolVersion;
import org.apache.hive.service.cli.thrift.TSessionHandle;
-import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.conn.ssl.SSLContexts;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
@@ -84,6 +96,8 @@
private static final String HIVE_USE_SSL = "ssl";
private static final String HIVE_SSL_TRUST_STORE = "sslTrustStore";
private static final String HIVE_SSL_TRUST_STORE_PASSWORD = "trustStorePassword";
+ // TODO HIVE-6286: Add support for PKCS12 keystore format
+ private static final String HIVE_SSL_TRUST_STORE_TYPE = "JKS";
private final String jdbcURI;
private final String host;
@@ -162,22 +176,25 @@ private void openTransport() throws SQLException {
}
private TTransport createHttpTransport() throws SQLException {
+ CloseableHttpClient httpClient;
// http path should begin with "/"
String httpPath;
- httpPath = hiveConfMap.get(HiveConf.ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH.varname);
+ httpPath = hiveConfMap.get(
+ HiveConf.ConfVars.HIVE_SERVER2_THRIFT_HTTP_PATH.varname);
if(httpPath == null) {
httpPath = "/";
}
if(!httpPath.startsWith("/")) {
httpPath = "/" + httpPath;
}
-
- DefaultHttpClient httpClient = new DefaultHttpClient();
- String httpUrl = hiveConfMap.get(HiveConf.ConfVars.HIVE_SERVER2_TRANSPORT_MODE.varname) +
- "://" + host + ":" + port + httpPath;
- httpClient.addRequestInterceptor(
- new HttpBasicAuthInterceptor(getUserName(), getPasswd())
- );
+ Boolean useSsl = "true".equalsIgnoreCase(sessConfMap.get(HIVE_USE_SSL));
+ // Create an http client from the configs
+ httpClient = getHttpClient(useSsl);
+
+ // Create the http/https url
+ // JDBC driver will set up an https url if ssl is enabled, otherwise http
+ String schemeName = useSsl ? "https" : "http";
+ String httpUrl = schemeName + "://" + host + ":" + port + httpPath;
try {
transport = new THttpClient(httpUrl, httpClient);
}
@@ -189,6 +206,45 @@ private TTransport createHttpTransport() throws SQLException {
return transport;
}
+ private CloseableHttpClient getHttpClient(Boolean useSsl) throws SQLException {
+ // Add an interceptor to pass username/password in the header
+ // for basic preemtive http authentication at the server
+ // In https mode, the entire information is encrypted
+ HttpRequestInterceptor authInterceptor = new HttpBasicAuthInterceptor(
+ getUserName(), getPasswd());
+ if (useSsl) {
+ String sslTrustStorePath = sessConfMap.get(HIVE_SSL_TRUST_STORE);
+ String sslTrustStorePassword = sessConfMap.get(
+ HIVE_SSL_TRUST_STORE_PASSWORD);
+ KeyStore sslTrustStore;
+ SSLContext sslContext;
+ if (sslTrustStorePath == null || sslTrustStorePath.isEmpty()) {
+ // Create a default client context based on standard JSSE trust material
+ sslContext = SSLContexts.createDefault();
+ } else {
+ // Pick trust store config from the given path
+ try {
+ sslTrustStore = KeyStore.getInstance(HIVE_SSL_TRUST_STORE_TYPE);
+ sslTrustStore.load(new FileInputStream(sslTrustStorePath),
+ sslTrustStorePassword.toCharArray());
+ sslContext = SSLContexts.custom().loadTrustMaterial(
+ sslTrustStore).build();
+ }
+ catch (Exception e) {
+ String msg = "Could not create an https connection to " +
+ jdbcURI + ". " + e.getMessage();
+ throw new SQLException(msg, " 08S01", e);
+ }
+ }
+ return HttpClients.custom().setSslcontext(
+ sslContext).addInterceptorFirst(authInterceptor).build();
+ }
+ else {
+ // Create a plain http client
+ return HttpClients.custom().addInterceptorFirst(authInterceptor).build();
+ }
+ }
+
private TTransport createBinaryTransport() throws SQLException {
try {
// handle secure connection if specified
@@ -201,8 +257,8 @@ private TTransport createBinaryTransport() throws SQLException {
try {
saslQOP = SaslQOP.fromString(sessConfMap.get(HIVE_AUTH_QOP));
} catch (IllegalArgumentException e) {
- throw new SQLException("Invalid " + HIVE_AUTH_QOP + " parameter. " + e.getMessage(),
- "42000", e);
+ throw new SQLException("Invalid " + HIVE_AUTH_QOP +
+ " parameter. " + e.getMessage(), "42000", e);
}
}
saslProps.put(Sasl.QOP, saslQOP.toString());
diff --git a/pom.xml b/pom.xml
index 41f5337..598f7b0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -102,7 +102,7 @@
0.96.0-hadoop1
0.96.0-hadoop2
- 4.2.5
+ 4.3.2
4.2.4
1.9.2
0.3.2
@@ -111,6 +111,7 @@
6.1.26
7.6.0.v20120127
+ 7.6.0.v20120127
1.14
0.9.94
1.1
diff --git a/service/pom.xml b/service/pom.xml
index dff3174..b1002e2 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -67,14 +67,9 @@
${commons-logging.version}
- org.mortbay.jetty
- jetty
- ${jetty.version}
-
-
- org.mortbay.jetty
- jetty-util
- ${jetty.version}
+ org.eclipse.jetty.aggregate
+ jetty-all
+ ${jetty.hive-service.version}
org.apache.thrift
diff --git a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
index b5a6138..26bda5a 100644
--- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
+++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftCLIService.java
@@ -59,7 +59,7 @@
protected int portNum;
protected InetSocketAddress serverAddress;
protected TServer server;
- protected org.mortbay.jetty.Server httpServer;
+ protected org.eclipse.jetty.server.Server httpServer;
private boolean isStarted = false;
protected boolean isEmbedded = false;
diff --git a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
index e487a7f..33d8c0f 100644
--- a/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
+++ b/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpCLIService.java
@@ -26,10 +26,12 @@
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.TServlet;
-import org.mortbay.jetty.nio.SelectChannelConnector;
-import org.mortbay.jetty.servlet.Context;
-import org.mortbay.jetty.servlet.ServletHolder;
-import org.mortbay.thread.QueuedThreadPool;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
public class ThriftHttpCLIService extends ThriftCLIService {
@@ -74,16 +76,32 @@ public void run() {
httpPath = httpPath + "/*";
}
}
-
- httpServer = new org.mortbay.jetty.Server();
-
+
+ httpServer = new org.eclipse.jetty.server.Server();
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMinThreads(minWorkerThreads);
threadPool.setMaxThreads(maxWorkerThreads);
httpServer.setThreadPool(threadPool);
- SelectChannelConnector connector = new SelectChannelConnector();
- connector.setPort(portNum);
+ SelectChannelConnector connector;
+ Boolean useSsl = hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_USE_SSL);
+ String schemeName = useSsl ? "https" : "http";
+
+ if (useSsl) {
+ String keyStorePath = hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH).trim();
+ String keyStorePassword = hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD);
+ if (keyStorePath.isEmpty()) {
+ throw new IllegalArgumentException(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname +
+ " Not configured for SSL connection");
+ }
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ sslContextFactory.setKeyStorePath(keyStorePath);
+ sslContextFactory.setKeyStorePassword(keyStorePassword);
+ connector = new SslSelectChannelConnector(sslContextFactory);
+ } else {
+ connector = new SelectChannelConnector();
+ }
+ connector.setPort(portNum);
// Linux:yes, Windows:no
connector.setReuseAddress(!Shell.WINDOWS);
httpServer.addConnector(connector);
@@ -93,12 +111,15 @@ public void run() {
TProtocolFactory protocolFactory = new TBinaryProtocol.Factory();
TServlet thriftHttpServlet = new ThriftHttpServlet(processor, protocolFactory);
- final Context context = new Context(httpServer, "/", Context.SESSIONS);
+
+ final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath("/");
+ httpServer.setHandler(context);
context.addServlet(new ServletHolder(thriftHttpServlet), httpPath);
// TODO: check defaults: maxTimeout, keepalive, maxBodySize, bodyRecieveDuration, etc.
httpServer.start();
- String msg = "Starting CLIService in Http mode on port " + portNum +
+ String msg = "Starting CLIService in " + schemeName + " mode on port " + portNum +
" path=" + httpPath +
" with " + minWorkerThreads + ".." + maxWorkerThreads + " worker threads";
LOG.info(msg);