Repository: hive Updated Branches: refs/heads/master cfdb433bc -> cdba00c96
HIVE-20555: HiveServer2: Preauthenticated subject for http transport is not retained for entire duration of http communication in some cases (Vaibhav Gumashta reviewed by Daniel Dai) Project: http://git-wip-us.apache.org/repos/asf/hive/repo Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/cdba00c9 Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/cdba00c9 Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/cdba00c9 Branch: refs/heads/master Commit: cdba00c96fd86c4f9c28dbaa411727f1666d26cb Parents: cfdb433 Author: Vaibhav Gumashta <[email protected]> Authored: Fri Sep 21 16:27:15 2018 -0700 Committer: Vaibhav Gumashta <[email protected]> Committed: Fri Sep 21 16:32:35 2018 -0700 ---------------------------------------------------------------------- .../org/apache/hive/jdbc/HiveConnection.java | 19 +++++++++++++--- .../jdbc/HttpKerberosRequestInterceptor.java | 23 +++++++++---------- .../apache/hive/service/auth/HttpAuthUtils.java | 24 +++++--------------- 3 files changed, 33 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hive/blob/cdba00c9/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java ---------------------------------------------------------------------- diff --git a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java index 335995c..8d5aa70 100644 --- a/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java +++ b/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java @@ -70,6 +70,7 @@ import org.slf4j.LoggerFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; +import javax.security.auth.Subject; import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import java.io.BufferedReader; @@ -81,6 +82,8 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; +import java.security.AccessControlContext; +import java.security.AccessController; import java.security.KeyStore; import java.security.SecureRandom; import java.sql.Array; @@ -140,6 +143,7 @@ public class HiveConnection implements java.sql.Connection { private String initFile = null; private String wmPool = null, wmApp = null; private Properties clientInfo; + private Subject loggedInSubject; /** * Get all direct HiveServer2 URLs from a ZooKeeper based HiveServer2 URL @@ -478,15 +482,24 @@ public class HiveConnection implements java.sql.Connection { } // Configure http client for kerberos/password based authentication if (isKerberosAuthMode()) { + if (assumeSubject) { + // With this option, we're assuming that the external application, + // using the JDBC driver has done a JAAS kerberos login already + AccessControlContext context = AccessController.getContext(); + loggedInSubject = Subject.getSubject(context); + if (loggedInSubject == null) { + throw new SQLException("The Subject is not set"); + } + } /** * Add an interceptor which sets the appropriate header in the request. * It does the kerberos authentication and get the final service ticket, * for sending to the server before every request. * In https mode, the entire information is encrypted */ - requestInterceptor = new HttpKerberosRequestInterceptor( - sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), host, getServerHttpUrl(useSsl), - assumeSubject, cookieStore, cookieName, useSsl, additionalHttpHeaders, customCookies); + requestInterceptor = new HttpKerberosRequestInterceptor(sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), + host, getServerHttpUrl(useSsl), loggedInSubject, cookieStore, cookieName, useSsl, additionalHttpHeaders, + customCookies); } else { // Check for delegation token, if present add it in the header String tokenStr = getClientDelegationToken(sessConfMap); http://git-wip-us.apache.org/repos/asf/hive/blob/cdba00c9/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java ---------------------------------------------------------------------- diff --git a/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java b/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java index 28d42d7..516825f 100644 --- a/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java +++ b/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java @@ -21,6 +21,8 @@ package org.apache.hive.jdbc; import java.util.Map; import java.util.concurrent.locks.ReentrantLock; +import javax.security.auth.Subject; + import org.apache.hive.service.auth.HttpAuthUtils; import org.apache.http.HttpException; import org.apache.http.HttpRequest; @@ -37,33 +39,30 @@ public class HttpKerberosRequestInterceptor extends HttpRequestInterceptorBase { String principal; String host; String serverHttpUrl; - boolean assumeSubject; + Subject loggedInSubject; // A fair reentrant lock private static ReentrantLock kerberosLock = new ReentrantLock(true); - public HttpKerberosRequestInterceptor(String principal, String host, String serverHttpUrl, - boolean assumeSubject, CookieStore cs, String cn, boolean isSSL, - Map<String, String> additionalHeaders, Map<String, String> customCookies) { + public HttpKerberosRequestInterceptor(String principal, String host, String serverHttpUrl, Subject loggedInSubject, + CookieStore cs, String cn, boolean isSSL, Map<String, String> additionalHeaders, + Map<String, String> customCookies) { super(cs, cn, isSSL, additionalHeaders, customCookies); this.principal = principal; this.host = host; this.serverHttpUrl = serverHttpUrl; - this.assumeSubject = assumeSubject; + this.loggedInSubject = loggedInSubject; } @Override - protected void addHttpAuthHeader(HttpRequest httpRequest, - HttpContext httpContext) throws Exception { - try { + protected void addHttpAuthHeader(HttpRequest httpRequest, HttpContext httpContext) throws Exception { + try { // Generate the service ticket for sending to the server. // Locking ensures the tokens are unique in case of concurrent requests kerberosLock.lock(); - String kerberosAuthHeader = HttpAuthUtils.getKerberosServiceTicket( - principal, host, serverHttpUrl, assumeSubject); + String kerberosAuthHeader = HttpAuthUtils.getKerberosServiceTicket(principal, host, serverHttpUrl, loggedInSubject); // Set the session key token (Base64 encoded) in the headers - httpRequest.addHeader(HttpAuthUtils.AUTHORIZATION + ": " + - HttpAuthUtils.NEGOTIATE + " ", kerberosAuthHeader); + httpRequest.addHeader(HttpAuthUtils.AUTHORIZATION + ": " + HttpAuthUtils.NEGOTIATE + " ", kerberosAuthHeader); } catch (Exception e) { throw new HttpException(e.getMessage(), e); } finally { http://git-wip-us.apache.org/repos/asf/hive/blob/cdba00c9/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java ---------------------------------------------------------------------- diff --git a/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java b/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java index 12e63da..d18ac87 100644 --- a/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java +++ b/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java @@ -18,8 +18,6 @@ package org.apache.hive.service.auth; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.security.SecureRandom; import java.util.Arrays; @@ -33,7 +31,6 @@ import javax.security.auth.Subject; import org.apache.commons.codec.binary.Base64; import org.apache.hadoop.hive.metastore.security.HadoopThriftAuthBridge; -import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.security.UserGroupInformation; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; @@ -64,23 +61,14 @@ public final class HttpAuthUtils { * @return Stringified Base64 encoded kerberosAuthHeader on success * @throws Exception */ - public static String getKerberosServiceTicket(String principal, String host, - String serverHttpUrl, boolean assumeSubject) throws Exception { - String serverPrincipal = - HadoopThriftAuthBridge.getBridge().getServerPrincipal(principal, host); - if (assumeSubject) { - // With this option, we're assuming that the external application, - // using the JDBC driver has done a JAAS kerberos login already - AccessControlContext context = AccessController.getContext(); - Subject subject = Subject.getSubject(context); - if (subject == null) { - throw new Exception("The Subject is not set"); - } - return Subject.doAs(subject, new HttpKerberosClientAction(serverPrincipal, serverHttpUrl)); + public static String getKerberosServiceTicket(String principal, String host, String serverHttpUrl, + Subject loggedInSubject) throws Exception { + String serverPrincipal = HadoopThriftAuthBridge.getBridge().getServerPrincipal(principal, host); + if (loggedInSubject != null) { + return Subject.doAs(loggedInSubject, new HttpKerberosClientAction(serverPrincipal, serverHttpUrl)); } else { // JAAS login from ticket cache to setup the client UserGroupInformation - UserGroupInformation clientUGI = - HadoopThriftAuthBridge.getBridge().getCurrentUGIWithConf("kerberos"); + UserGroupInformation clientUGI = HadoopThriftAuthBridge.getBridge().getCurrentUGIWithConf("kerberos"); return clientUGI.doAs(new HttpKerberosClientAction(serverPrincipal, serverHttpUrl)); } }
