diff --git common/src/java/org/apache/hadoop/hive/conf/HiveConf.java common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 6dadd9c..d16a794 100644 --- common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -774,6 +774,9 @@ HIVE_SERVER2_TABLE_TYPE_MAPPING("hive.server2.table.type.mapping", "CLASSIC", new StringsValidator("CLASSIC", "HIVE")), HIVE_SERVER2_SESSION_HOOK("hive.server2.session.hook", ""), + HIVE_SERVER2_USE_SSL("hive.server2.use.SSL", false), + HIVE_SERVER2_SSL_KEYSTORE_PATH("hive.server2.keystore.path", ""), + HIVE_SERVER2_SSL_KEYSTORE_PASSWORD("hive.server2.keystore.password", ""), HIVE_SECURITY_COMMAND_WHITELIST("hive.security.command.whitelist", "set,reset,dfs,add,delete,compile"), diff --git data/files/keystore.jks data/files/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..469d8a543a4d2a94535996ceee2a24891699b1cc GIT binary patch literal 2248 zcmchYc|6qn8pmhGSSK8N#uk#D-xzBsOBlPcWJ%eYvKt!9bZ>*9AskZ?hGZ*ZEJK!L zJ+ft=bdIU1kg`T0##XM*z4vv`>vjJ>e>{IY@9*n*UeD|EeO{mE$Lfz&5C{Z03h9p}+ z(#5${Qlrizjd*Qt=3Y;+F6i8J>X;dp-8O4&ppIWly63Y$Su+~i$j^H_U7hsxzU@}* z#OCn(Z zU{7sNAB~VRuL8JrNrK~q#6rAJ*ICkuE4NSp!WkpieK#@#EAOc2TU%3KH%WqHY>Iw)QG#c#aThm7Tvs zW9V+`^31@As*EJH_$HMiqL7iy`dENe#S6DgSk3P=pqMIW_vBXe3MFMW-sg}Jzi)+Xrw6Hc-|R%_>A>}c53Q2M2@-qHKlPY7a< zlJzoLawdWFprzUu>){rvT(HZuXmzU9x}>RMw&QPcdPRv0RGr+2+>V&VwTT7m5JFJj zy@C>A71mRU-lD0d+?tZzIt(5$*4CIS$dF4R##Tb z8;&bvn8cM6q7GJ}_mx9**jK)X=oJNxFy|VpsQD#Qb$7Rll4gw0hb`t;n^YetCe(6< zz@F1x%oip3Pxnfq+%K^L^Lq9oIHlutMfigC9=iArL7IeVJGDS^y8%WP>C=MA8k*pl zZO3S88Z@F4d@RoDQhZ#bWY%Zod+l?Y2M!FavmNeByx%Y6De9#eSYYN=*Ct%jKkhb7 z7!L^ALZ?H2oycfg{#3~Movg?CI)4_uFQ&(bJE^7S z!p`?Kr<~zrICUyg`2dJE6tuapVuU6n*g!|I#g4{t8=AICj!c#7QE^))msIFV8eRdN zb$&0v$VEz2j=%^NAthnEepOgNAVTum$$HBxgUMvytWkID#jx5riKo_E;xY@dvrc|f zq{ipCQf}W$I1DMdki!{zxf%1FY45A{HZ!eHqbPDwbZ(=s9~U~Za~}D;om--oLZN3J|MW(74-Fl_ z00d&Y0T9{n01@I>%mx8NAW)AkU2cGvgIk4!BC&YEU>G|H2u1vIWSMMkP!1tZxA2hg zh}iJ|60ZLvoc|;IM~#lEc!W4iv3>!87z8f>`w3t|P}Gq%BZL9LpDCLV?BDMvep29s z7%u{e0JM;Rjh7X7i@K!LlA3&*^ut`zIhhEmbe33oAAK3c%)f)!n!lvCC z)@~Z5e0Fc6pwaU1a+zb9u&ZgZdBT;tw@;L44^i;spji3A8R=Y=HgK;Oe>LL;^H`w$ zV`6;**W~093NhZ{Wky#Om+zSyecGaoZF@wf9c-fKvT|LYDKvemB%Hfe{a(G=!(r#y zC%i(;zO=}f9HT-rD@jU-*RV!kCHDhEYl`ZaDtG7hb85hWHU+E=n7pwME%H#E4 z48oiGvoGg886I})=dH$psxr{a-C@tS&DgT}(M*Jbj}hF@=A=nxGWLoTgbfS=m&pP$ zfYi}%O7THOp~Cv>`L|#e+4|*qBy#!)?VWN9d&yr#Jld)w5y2p#JskQtuCO@9R;D*< zh|m@29h@W{q_REwfrDj?r&9uKjv*9#lPxZ+pJtubxw&mJAFuY-&rSVva9edbtL^a` zVC#wxGu$k0QvPtYF=s(WS2IqRkJJ|3lm;_~Z z4D~zPz5hq}zMH7D3D)rDrvl5fhMj@$a;}$*ALPC~b%wQ+J+q%DsH`B3ntZpOqPQ~l z`HgUjJvs7SlUI2_yz)VFX2b=_v1m%>-M%Z+83QV}6oQgs&wZhaV=d1~TPwW~u?lQG z(N<|lUq}mHz1uBT^Xj@`%d(M6ZFgv>=~%lllQ15KC90j(5|wDa!{FY(SAs`3qvi|_ Js_3iE{{opy;Gh5i literal 0 HcmV?d00001 diff --git data/files/truststore.jks data/files/truststore.jks new file mode 100644 index 0000000000000000000000000000000000000000..9c5d703fba6c8c23bf6ee8f431d6d0fc35bf9ee1 GIT binary patch literal 958 zcmezO_TO6u1_mY|W(3n58JT6NSt&`$Kmo_cw>h&JSR?dI4J;WLm}?E1m@5sMm=YH- zGchtTu|(`Q<22x9f#b+b1XMYS;eE$kI*1xT_?4P^!=i2W- zyJjwX`0LZ`EpGo)7W*$232|(3Zb(~yXS2qJB_2{OndQnS9>`7C+Rb<*ihs?Glec*? zd{;DWY~Z+j`K5>9`Mpt27qumo4?RA+W4mU-?xp=3{(KI6Jb8M^F4e71SJt@{ueqnY zCc^K>uCq5P)8GGpw$W?nD%RC`6Am?n@jqO()9~5bo-?mIm@B^QjFE1(3uc;-AotQF z*nLmO%oQI6Ec3P=o02kP^Xb!}$9UJ2Fs$kce03oA@HZ#sDg1%A4OQc9q!PVU9Qs-c z(qx&K85tNCD;mff$O2G2LJL^K^Km?{LU?4Iw z2>&Vxlqi|Ipv+tTNYSaf{TVS?&61f~-_AZ_`)*r#ab~g?kD>aJ7T4&HR^P2mTfaFx ztJk@c7^?dwYxkOE-*>NgXJ8vM-Ni&~zr}z5Hn;wMd7sWXNoJ*|$~GKZ=^OpIdDFtr zO$X{MR?M2hI6bP~&x=>pA+vAqsbfJt_p0-Lhlw9L8EnSGOvrrqy3 zuGOiU*<9}OezjzQn~R*M#z|54jGYR*S6W|u-j(%s(gE?cSE{VHzp@ElcOWOn@!THU i+jZwF3Yv86jpP{Duj5kx`QB$`i> startupTimeout) { + throw new TimeoutException("Couldn't access new HiveServer: " + getJdbcURL()); + } + try { + sessionHandle = hs2Client.openSession("foo", "bar"); + } catch (Exception e) { + // service not started yet + continue; + } + hs2Client.closeSession(sessionHandle); + break; + } while (true); + } + +} diff --git itests/hive-unit/src/test/java/org/apache/hive/jdbc/miniHS2/TestHiveServer2.java itests/hive-unit/src/test/java/org/apache/hive/jdbc/miniHS2/TestHiveServer2.java new file mode 100644 index 0000000..eb08628 --- /dev/null +++ itests/hive-unit/src/test/java/org/apache/hive/jdbc/miniHS2/TestHiveServer2.java @@ -0,0 +1,69 @@ +/** + * 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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.hive.jdbc.miniHS2; + +import static org.junit.Assert.assertFalse; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hive.service.cli.CLIServiceClient; +import org.apache.hive.service.cli.OperationHandle; +import org.apache.hive.service.cli.RowSet; +import org.apache.hive.service.cli.SessionHandle; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestHiveServer2 { + + private static MiniHS2 miniHS2 = null; + private Map confOverlay; + + @BeforeClass + public static void beforeTest() throws IOException { + miniHS2 = new MiniHS2(new HiveConf()); + } + + @Before + public void setUp() throws Exception { + miniHS2.start(); + confOverlay = new HashMap(); + } + + @After + public void tearDown() { + miniHS2.stop(); + } + + @Test + public void testConnection() throws Exception { + String tabName = "testTab1"; + CLIServiceClient serviceClient = miniHS2.getServiceClient(); + SessionHandle sessHandle = serviceClient.openSession("foo", "bar"); + serviceClient.executeStatement(sessHandle, "DROP TABLE IF EXISTS tab", confOverlay); + serviceClient.executeStatement(sessHandle, "CREATE TABLE " + tabName + " (id INT)", confOverlay); + OperationHandle opHandle = serviceClient.executeStatement(sessHandle, "SHOW TABLES", confOverlay); + RowSet rowSet = serviceClient.fetchResults(opHandle); + assertFalse(rowSet.getSize() == 0); + } +} diff --git jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java index 5a6ce44..5a0f84c 100644 --- jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java +++ jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java @@ -24,6 +24,7 @@ import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.DriverManager; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; @@ -46,6 +47,7 @@ import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.ql.session.SessionState; +import org.apache.hive.service.auth.HiveAuthFactory; import org.apache.hive.service.auth.KerberosSaslHelper; import org.apache.hive.service.auth.PlainSaslHelper; import org.apache.hive.service.auth.SaslQOP; @@ -61,7 +63,6 @@ import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.THttpClient; -import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; @@ -78,6 +79,10 @@ private static final String HIVE_AUTH_PASSWD = "password"; private static final String HIVE_ANONYMOUS_USER = "anonymous"; private static final String HIVE_ANONYMOUS_PASSWD = "anonymous"; + 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"; + private final String jdbcURI; private final String host; private final int port; @@ -91,8 +96,10 @@ private SQLWarning warningChain = null; private TSessionHandle sessHandle = null; private final List supportedProtocols = new LinkedList(); + private int loginTimeout = 0; public HiveConnection(String uri, Properties info) throws SQLException { + loginTimeout = DriverManager.getLoginTimeout(); jdbcURI = uri; // parse the connection uri Utils.JdbcConnectionParams connParams = Utils.parseURL(jdbcURI); @@ -177,26 +184,26 @@ private TTransport createHttpTransport() throws SQLException { } private TTransport createBinaryTransport() throws SQLException { - transport = new TSocket(host, port); - // handle secure connection if specified - if (!sessConfMap.containsKey(HIVE_AUTH_TYPE) - || !sessConfMap.get(HIVE_AUTH_TYPE).equals(HIVE_AUTH_SIMPLE)) { - try { + try { + // handle secure connection if specified + if (!HIVE_AUTH_SIMPLE.equals(sessConfMap.get(HIVE_AUTH_TYPE))) { // If Kerberos if (sessConfMap.containsKey(HIVE_AUTH_PRINCIPAL)) { Map saslProps = new HashMap(); SaslQOP saslQOP = SaslQOP.AUTH; - if(sessConfMap.containsKey(HIVE_AUTH_QOP)) { + if (sessConfMap.containsKey(HIVE_AUTH_QOP)) { 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()); saslProps.put(Sasl.SERVER_AUTH, "true"); transport = KerberosSaslHelper.getKerberosTransport( - sessConfMap.get(HIVE_AUTH_PRINCIPAL), host, transport, saslProps); + sessConfMap.get(HIVE_AUTH_PRINCIPAL), host, + HiveAuthFactory.getSocketTransport(host, port, loginTimeout), saslProps); } else { String userName = sessConfMap.get(HIVE_AUTH_USER); if ((userName == null) || userName.isEmpty()) { @@ -206,12 +213,30 @@ private TTransport createBinaryTransport() throws SQLException { if ((passwd == null) || passwd.isEmpty()) { passwd = HIVE_ANONYMOUS_PASSWD; } + String useSslStr = sessConfMap.get(HIVE_USE_SSL); + if ("true".equalsIgnoreCase(useSslStr)) { + String sslTrustStore = sessConfMap.get(HIVE_SSL_TRUST_STORE); + String sslTrustStorePassword = sessConfMap.get(HIVE_SSL_TRUST_STORE_PASSWORD); + if (sslTrustStore == null || sslTrustStore.isEmpty()) { + transport = HiveAuthFactory.getSSLSocket(host, port, loginTimeout); + } else { + transport = HiveAuthFactory.getSSLSocket(host, port, loginTimeout, + sslTrustStore, sslTrustStorePassword); + } + } else { + transport = HiveAuthFactory.getSocketTransport(host, port, loginTimeout); + } transport = PlainSaslHelper.getPlainTransport(userName, passwd, transport); } - } catch (SaslException e) { - throw new SQLException("Could not create secure connection to " - + jdbcURI + ": " + e.getMessage(), " 08S01", e); + } else { + transport = HiveAuthFactory.getSocketTransport(host, port, loginTimeout); } + } catch (SaslException e) { + throw new SQLException("Could not create secure connection to " + + jdbcURI + ": " + e.getMessage(), " 08S01", e); + } catch (TTransportException e) { + throw new SQLException("Could not create connection to " + + jdbcURI + ": " + e.getMessage(), " 08S01", e); } return transport; } diff --git metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index 02530b0..01c2626 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -277,6 +277,10 @@ public static Integer get() { return threadLocalId.get(); } + public static void resetDefaultDBFlag() { + createDefaultDB = false; + } + public HMSHandler(String name) throws MetaException { super(name); hiveConf = new HiveConf(this.getClass()); @@ -4109,7 +4113,6 @@ public static IHMSHandler newHMSHandler(String name, HiveConf hiveConf) throws M } - /** * Discard a current delegation token. * diff --git service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java index 5a66a6c..d80649f 100644 --- service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java +++ service/src/java/org/apache/hive/service/auth/HiveAuthFactory.java @@ -18,6 +18,12 @@ package org.apache.hive.service.auth; import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Map; import javax.security.auth.login.LoginException; import javax.security.sasl.Sasl; @@ -28,15 +34,15 @@ import org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge; import org.apache.hive.service.cli.thrift.ThriftCLIService; import org.apache.thrift.TProcessorFactory; +import org.apache.thrift.transport.TSSLTransportFactory; +import org.apache.thrift.transport.TServerSocket; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; import org.apache.thrift.transport.TTransportFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.MessageFormat; -import java.util.HashMap; -import java.util.Map; - public class HiveAuthFactory { private static final Logger LOG = LoggerFactory.getLogger(HiveAuthFactory.class); @@ -153,4 +159,44 @@ public static void loginFromKeytab(HiveConf hiveConf) throws IOException { } } + public static TTransport getSocketTransport(String host, int port, int loginTimeout) + throws TTransportException { + return new TSocket(host, port, loginTimeout); + } + + public static TTransport getSSLSocket(String host, int port, int loginTimeout) + throws TTransportException { + return TSSLTransportFactory.getClientSocket(host, port, loginTimeout); + } + + public static TTransport getSSLSocket(String host, int port, int loginTimeout, + String trustStorePath, String trustStorePassWord) throws TTransportException { + TSSLTransportFactory.TSSLTransportParameters params = + new TSSLTransportFactory.TSSLTransportParameters(); + params.setTrustStore(trustStorePath, trustStorePassWord); + params.requireClientAuth(true); + return TSSLTransportFactory.getClientSocket(host, port, loginTimeout, params); + } + + public static TServerSocket getServerSocket(String hiveHost, int portNum) + throws TTransportException { + InetSocketAddress serverAddress = null; + if (hiveHost != null && !hiveHost.isEmpty()) { + serverAddress = new InetSocketAddress(hiveHost, portNum); + } else { + serverAddress = new InetSocketAddress(portNum); + } + return new TServerSocket(serverAddress ); + } + + public static TServerSocket getServerSSLSocket(String hiveHost, int portNum, + String keyStorePath, String keyStorePassWord) throws TTransportException, UnknownHostException { + TSSLTransportFactory.TSSLTransportParameters params = + new TSSLTransportFactory.TSSLTransportParameters(); + params.setKeyStore(keyStorePath, keyStorePassWord); + + return TSSLTransportFactory.getServerSocket(portNum, 10000, + InetAddress.getByName(hiveHost), params); + } + } diff --git service/src/java/org/apache/hive/service/cli/thrift/ThriftBinaryCLIService.java service/src/java/org/apache/hive/service/cli/thrift/ThriftBinaryCLIService.java index 9c8f5c1..6fbc847 100644 --- service/src/java/org/apache/hive/service/cli/thrift/ThriftBinaryCLIService.java +++ service/src/java/org/apache/hive/service/cli/thrift/ThriftBinaryCLIService.java @@ -64,7 +64,19 @@ public void run() { minWorkerThreads = hiveConf.getIntVar(ConfVars.HIVE_SERVER2_THRIFT_MIN_WORKER_THREADS); maxWorkerThreads = hiveConf.getIntVar(ConfVars.HIVE_SERVER2_THRIFT_MAX_WORKER_THREADS); - TThreadPoolServer.Args sargs = new TThreadPoolServer.Args(new TServerSocket(serverAddress)) + TServerSocket serverSocket = null; + if (!hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_USE_SSL)) { + serverSocket = HiveAuthFactory.getServerSocket(hiveHost, portNum); + } else { + String keyStorePath = hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH).trim(); + if (keyStorePath.isEmpty()) { + throw new IllegalArgumentException(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname + + " Not configured for SSL connection"); + } + serverSocket = HiveAuthFactory.getServerSSLSocket(hiveHost, portNum, + keyStorePath, hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD)); + } + TThreadPoolServer.Args sargs = new TThreadPoolServer.Args(serverSocket) .processorFactory(processorFactory) .transportFactory(transportFactory) .protocolFactory(new TBinaryProtocol.Factory()) @@ -82,4 +94,4 @@ public void run() { } } -} \ No newline at end of file +} diff --git shims/0.20/src/main/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java shims/0.20/src/main/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java index 623ebcd..17f4a94 100644 --- shims/0.20/src/main/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java +++ shims/0.20/src/main/java/org/apache/hadoop/hive/shims/Hadoop20Shims.java @@ -611,6 +611,10 @@ public Path createDelegationTokenFile(Configuration conf) throws IOException { @Override public UserGroupInformation createRemoteUser(String userName, List groupNames) { + if (groupNames.isEmpty()) { + groupNames = new ArrayList(); + groupNames.add(userName); + } return new UnixUserGroupInformation(userName, groupNames.toArray(new String[0])); } diff --git shims/common-secure/src/main/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java shims/common-secure/src/main/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java index fd274a6..fd0d526 100644 --- shims/common-secure/src/main/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java +++ shims/common-secure/src/main/java/org/apache/hadoop/hive/shims/HadoopShimsSecure.java @@ -545,7 +545,6 @@ public Path createDelegationTokenFile(Configuration conf) throws IOException { return tokenPath; } - @Override public UserGroupInformation createProxyUser(String userName) throws IOException { return UserGroupInformation.createProxyUser(