FAQ
Author: vgumashta
Date: Wed Nov 5 03:26:13 2014
New Revision: 1636794

URL: http://svn.apache.org/r1636794
Log:
HIVE-8705: Support using pre-authenticated subject in kerberized HiveServer2 HTTP mode (Vaibhav Gumashta reviewed by Thejas Nair)

Modified:
     hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java
     hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java
     hive/branches/branch-0.14/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java
     hive/branches/branch-0.14/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java

Modified: hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java
URL: http://svn.apache.org/viewvc/hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java?rev=1636794&r1=1636793&r2=1636794&view=diff
==============================================================================
--- hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java (original)
+++ hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HiveConnection.java Wed Nov 5 03:26:13 2014
@@ -99,6 +99,7 @@ public class HiveConnection implements j
    private JdbcConnectionParams connParams;
    private final boolean isEmbeddedMode;
    private TTransport transport;
+ private boolean assumeSubject;
    // TODO should be replaced by CliServiceClient
    private TCLIService.Iface client;
    private boolean isClosed = true;
@@ -177,6 +178,9 @@ public class HiveConnection implements j
    private void openTransport() throws SQLException {
      while (true) {
        try {
+ assumeSubject =
+ JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE_FROM_SUBJECT.equals(sessConfMap
+ .get(JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE));
          transport = isHttpTransportMode() ? createHttpTransport() : createBinaryTransport();
          if (!transport.isOpen()) {
            LOG.info("Will try to open client transport with JDBC Uri: " + jdbcUriString);
@@ -265,8 +269,9 @@ public class HiveConnection implements j
         * In https mode, the entire information is encrypted
         * TODO: Optimize this with a mix of kerberos + using cookie.
         */
- requestInterceptor = new HttpKerberosRequestInterceptor(
- sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), host, getServerHttpUrl(false));
+ requestInterceptor =
+ new HttpKerberosRequestInterceptor(sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL),
+ host, getServerHttpUrl(useSsl), assumeSubject);
      }
      else {
        /**
@@ -351,8 +356,6 @@ public class HiveConnection implements j
            }
            saslProps.put(Sasl.QOP, saslQOP.toString());
            saslProps.put(Sasl.SERVER_AUTH, "true");
- boolean assumeSubject = JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE_FROM_SUBJECT.equals(sessConfMap
- .get(JdbcConnectionParams.AUTH_KERBEROS_AUTH_TYPE));
            transport = KerberosSaslHelper.getKerberosTransport(
                sessConfMap.get(JdbcConnectionParams.AUTH_PRINCIPAL), host,
                HiveAuthFactory.getSocketTransport(host, port, loginTimeout), saslProps,

Modified: hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java
URL: http://svn.apache.org/viewvc/hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java?rev=1636794&r1=1636793&r2=1636794&view=diff
==============================================================================
--- hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java (original)
+++ hive/branches/branch-0.14/jdbc/src/java/org/apache/hive/jdbc/HttpKerberosRequestInterceptor.java Wed Nov 5 03:26:13 2014
@@ -39,15 +39,17 @@ public class HttpKerberosRequestIntercep
    String principal;
    String host;
    String serverHttpUrl;
+ boolean assumeSubject;

    // A fair reentrant lock
    private static ReentrantLock kerberosLock = new ReentrantLock(true);

    public HttpKerberosRequestInterceptor(String principal, String host,
- String serverHttpUrl) {
+ String serverHttpUrl, boolean assumeSubject) {
      this.principal = principal;
      this.host = host;
      this.serverHttpUrl = serverHttpUrl;
+ this.assumeSubject = assumeSubject;
    }

    @Override
@@ -59,7 +61,7 @@ public class HttpKerberosRequestIntercep
        // Locking ensures the tokens are unique in case of concurrent requests
        kerberosLock.lock();
        kerberosAuthHeader = HttpAuthUtils.getKerberosServiceTicket(
- principal, host, serverHttpUrl);
+ principal, host, serverHttpUrl, assumeSubject);
        // Set the session key token (Base64 encoded) in the headers
        httpRequest.addHeader(HttpAuthUtils.AUTHORIZATION + ": " +
            HttpAuthUtils.NEGOTIATE + " ", kerberosAuthHeader);

Modified: hive/branches/branch-0.14/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java
URL: http://svn.apache.org/viewvc/hive/branches/branch-0.14/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java?rev=1636794&r1=1636793&r2=1636794&view=diff
==============================================================================
--- hive/branches/branch-0.14/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java (original)
+++ hive/branches/branch-0.14/service/src/java/org/apache/hive/service/auth/HttpAuthUtils.java Wed Nov 5 03:26:13 2014
@@ -18,16 +18,18 @@

  package org.apache.hive.service.auth;

-import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
  import java.security.PrivilegedExceptionAction;

+import javax.security.auth.Subject;
+
  import org.apache.commons.codec.binary.Base64;
  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;
  import org.ietf.jgss.GSSContext;
-import org.ietf.jgss.GSSCredential;
  import org.ietf.jgss.GSSManager;
  import org.ietf.jgss.GSSName;
  import org.ietf.jgss.Oid;
@@ -36,60 +38,54 @@ import org.ietf.jgss.Oid;
   * Utility functions for HTTP mode authentication.
   */
  public final class HttpAuthUtils {
-
    public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
    public static final String AUTHORIZATION = "Authorization";
    public static final String BASIC = "Basic";
    public static final String NEGOTIATE = "Negotiate";
-
- /**
- * @return Stringified Base64 encoded kerberosAuthHeader on success
- */
- public static String getKerberosServiceTicket(String principal, String host, String serverHttpUrl)
- throws IOException, InterruptedException {
- UserGroupInformation clientUGI = getClientUGI("kerberos");
- String serverPrincipal = getServerPrincipal(principal, host);
- // Uses the Ticket Granting Ticket in the UserGroupInformation
- return clientUGI.doAs(
- new HttpKerberosClientAction(serverPrincipal, clientUGI.getUserName(), serverHttpUrl));
- }

    /**
- * Get server principal and verify that hostname is present.
- */
- private static String getServerPrincipal(String principal, String host) throws IOException {
- return ShimLoader.getHadoopThriftAuthBridge().getServerPrincipal(principal, host);
- }
-
- /**
- * JAAS login to setup the client UserGroupInformation.
- * Sets up the Kerberos Ticket Granting Ticket,
- * in the client UserGroupInformation object.
- *
- * @return Client's UserGroupInformation
+ * @return Stringified Base64 encoded kerberosAuthHeader on success
+ * @throws Exception
     */
- public static UserGroupInformation getClientUGI(String authType) throws IOException {
- return ShimLoader.getHadoopThriftAuthBridge().getCurrentUGIWithConf(authType);
+ public static String getKerberosServiceTicket(String principal, String host,
+ String serverHttpUrl, boolean assumeSubject) throws Exception {
+ String serverPrincipal =
+ ShimLoader.getHadoopThriftAuthBridge().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));
+ } else {
+ // JAAS login from ticket cache to setup the client UserGroupInformation
+ UserGroupInformation clientUGI =
+ ShimLoader.getHadoopThriftAuthBridge().getCurrentUGIWithConf("kerberos");
+ return clientUGI.doAs(new HttpKerberosClientAction(serverPrincipal, serverHttpUrl));
+ }
    }

    private HttpAuthUtils() {
      throw new UnsupportedOperationException("Can't initialize class");
    }

+ /**
+ * We'll create an instance of this class within a doAs block so that the client's TGT credentials
+ * can be read from the Subject
+ */
    public static class HttpKerberosClientAction implements PrivilegedExceptionAction<String> {
-
      public static final String HTTP_RESPONSE = "HTTP_RESPONSE";
      public static final String SERVER_HTTP_URL = "SERVER_HTTP_URL";
      private final String serverPrincipal;
- private final String clientUserName;
      private final String serverHttpUrl;
      private final Base64 base64codec;
      private final HttpContext httpContext;

- public HttpKerberosClientAction(String serverPrincipal, String clientUserName,
- String serverHttpUrl) {
+ public HttpKerberosClientAction(String serverPrincipal, String serverHttpUrl) {
        this.serverPrincipal = serverPrincipal;
- this.clientUserName = clientUserName;
        this.serverHttpUrl = serverHttpUrl;
        base64codec = new Base64(0);
        httpContext = new BasicHttpContext();
@@ -102,38 +98,17 @@ public final class HttpAuthUtils {
        Oid mechOid = new Oid("1.2.840.113554.1.2.2");
        // Oid for kerberos principal name
        Oid krb5PrincipalOid = new Oid("1.2.840.113554.1.2.2.1");
-
        GSSManager manager = GSSManager.getInstance();
-
- // GSS name for client
- GSSName clientName = manager.createName(clientUserName, GSSName.NT_USER_NAME);
        // GSS name for server
        GSSName serverName = manager.createName(serverPrincipal, krb5PrincipalOid);
-
- // GSS credentials for client
- GSSCredential clientCreds =
- manager.createCredential(clientName, GSSCredential.DEFAULT_LIFETIME, mechOid,
- GSSCredential.INITIATE_ONLY);
-
- /*
- * Create a GSSContext for mutual authentication with the
- * server.
- * - serverName is the GSSName that represents the server.
- * - krb5Oid is the Oid that represents the mechanism to
- * use. The client chooses the mechanism to use.
- * - clientCreds are the client credentials
- */
+ // Create a GSSContext for authentication with the service.
+ // We're passing client credentials as null since we want them to be read from the Subject.
        GSSContext gssContext =
- manager.createContext(serverName, mechOid, clientCreds, GSSContext.DEFAULT_LIFETIME);
-
- // Mutual authentication not r
+ manager.createContext(serverName, mechOid, null, GSSContext.DEFAULT_LIFETIME);
        gssContext.requestMutualAuth(false);
-
        // Establish context
        byte[] inToken = new byte[0];
-
        byte[] outToken = gssContext.initSecContext(inToken, 0, inToken.length);
-
        gssContext.dispose();
        // Base64 encoded and stringified token for server
        return new String(base64codec.encode(outToken));

Modified: hive/branches/branch-0.14/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java
URL: http://svn.apache.org/viewvc/hive/branches/branch-0.14/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java?rev=1636794&r1=1636793&r2=1636794&view=diff
==============================================================================
--- hive/branches/branch-0.14/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java (original)
+++ hive/branches/branch-0.14/service/src/java/org/apache/hive/service/cli/thrift/ThriftHttpServlet.java Wed Nov 5 03:26:13 2014
@@ -208,11 +208,9 @@ public class ThriftHttpServlet extends T

          // Create a GSS context
          gssContext = manager.createContext(serverCreds);
-
          // Get service ticket from the authorization header
          String serviceTicketBase64 = getAuthHeader(request, authType);
          byte[] inToken = Base64.decodeBase64(serviceTicketBase64.getBytes());
-
          gssContext.acceptSecContext(inToken, 0, inToken.length);
          // Authenticate or deny based on its context completion
          if (!gssContext.isEstablished()) {

Search Discussions

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 1 of 1 | next ›
Discussion Overview
groupcommits @
categorieshive, hadoop
postedNov 5, '14 at 3:26a
activeNov 5, '14 at 3:26a
posts1
users1
websitehive.apache.org

1 user in discussion

Vgumashta: 1 post

People

Translate

site design / logo © 2021 Grokbase