Browse Source

[beeswax] HiveServer2 impersonation support

Romain Rigaux 12 years ago
parent
commit
29bd135

+ 5 - 0
apps/beeswax/src/beeswax/hive_site.py

@@ -42,10 +42,12 @@ _CNF_METASTORE_URIS = 'hive.metastore.uris'
 _CNF_METASTORE_KERBEROS_PRINCIPAL = 'hive.metastore.kerberos.principal'
 _CNF_HIVESERVER2_KERBEROS_PRINCIPAL = 'hive.server2.authentication.kerberos.principal'
 _CNF_HIVESERVER2_AUTHENTICATION = 'hive.server2.authentication'
+_CNF_HIVESERVER2_IMPERSONATION = 'hive.server2.allow.user.substitution'
 
 # Host is whatever up to the colon. Allow and ignore a trailing slash.
 _THRIFT_URI_RE = re.compile("^thrift://([^:]+):(\d+)[/]?$")
 
+
 class MalformedHiveSiteException(Exception):
   """Parsing error class used internally"""
   pass
@@ -111,6 +113,9 @@ def get_hiveserver2_kerberos_principal():
 def get_hiveserver2_authentication():
   return get_conf().get(_CNF_HIVESERVER2_AUTHENTICATION, 'NONE').upper() # NONE == PLAIN SASL
 
+def has_hiveserver2_impersonation():
+  return get_conf().get(_CNF_HIVESERVER2_IMPERSONATION, 'FALSE').upper() == 'TRUE'
+
 def _parse_hive_site():
   """
   Parse hive-site.xml and store in _HIVE_SITE_DICT

+ 13 - 3
apps/beeswax/src/beeswax/server/hive_server2_lib.py

@@ -19,6 +19,7 @@ import logging
 import re
 import thrift
 
+from desktop.conf import KERBEROS
 from desktop.lib import thrift_util
 from hadoop import cluster
 
@@ -256,8 +257,9 @@ class HiveServerClient:
     self.query_server = query_server
     self.user = user
 
-    use_sasl, mechanism, kerberos_principal_short_name = HiveServerClient.get_security(query_server)
+    use_sasl, mechanism, kerberos_principal_short_name, has_hiveserver2_impersonation = HiveServerClient.get_security(query_server)
 
+    self.has_hiveserver2_impersonation = has_hiveserver2_impersonation
     self._client = thrift_util.get_client(TCLIService.Client,
                                           query_server['server_host'],
                                           query_server['server_port'],
@@ -272,6 +274,7 @@ class HiveServerClient:
   @classmethod
   def get_security(cls, query_server):
     principal = query_server['principal']
+    has_hiveserver2_impersonation = False # Specific to HiveServer2 protocol only
 
     if query_server['server_name'] == 'impala':
       cluster_conf = cluster.get_cluster_conf_for_job_submission()
@@ -285,17 +288,24 @@ class HiveServerClient:
       mechanism = 'NOSASL'
       if use_sasl:
         mechanism = HiveServerClient.HS2_MECHANISMS[hive_mechanism]
+      has_hiveserver2_impersonation = hive_site.has_hiveserver2_impersonation()
 
     if principal:
       kerberos_principal_short_name = principal.split('/', 1)[0]
     else:
       kerberos_principal_short_name = None
 
-    return use_sasl, mechanism, kerberos_principal_short_name
+    return use_sasl, mechanism, kerberos_principal_short_name, has_hiveserver2_impersonation
 
 
   def open_session(self, user):
-    req = TOpenSessionReq(username=user.username, configuration={})
+    if self.has_hiveserver2_impersonation:
+      kerberos_principal_short_name = KERBEROS.HUE_PRINCIPAL.get().split('/', 1)[0]
+      kwargs = {'username': kerberos_principal_short_name, 'configuration': {'hive.server2.proxy.user': user.username}}
+    else:
+      kwargs = {'username': user.username, 'configuration': {}}
+
+    req = TOpenSessionReq(**kwargs)
     res = self._client.OpenSession(req)
 
     sessionId = res.sessionHandle.sessionId

+ 16 - 9
apps/beeswax/src/beeswax/tests.py

@@ -1661,13 +1661,13 @@ def test_hiveserver2_get_security():
   beeswax_query_server = {'server_name': 'beeswax', 'principal': 'hue'}
   impala_query_server = {'server_name': 'impala', 'principal': 'impala'}
 
-  assert_equal((True, 'PLAIN', 'hue'), HiveServerClient.get_security(beeswax_query_server))
-  assert_equal((False, 'GSSAPI', 'impala'), HiveServerClient.get_security(impala_query_server))
+  assert_equal((True, 'PLAIN', 'hue', False), HiveServerClient.get_security(beeswax_query_server))
+  assert_equal((False, 'GSSAPI', 'impala', False), HiveServerClient.get_security(impala_query_server))
 
   cluster_conf = hadoop.cluster.get_cluster_conf_for_job_submission()
   finish = cluster_conf.SECURITY_ENABLED.set_for_testing(True)
   try:
-    assert_equal((True, 'GSSAPI', 'impala'), HiveServerClient.get_security(impala_query_server))
+    assert_equal((True, 'GSSAPI', 'impala', False), HiveServerClient.get_security(impala_query_server))
   finally:
     finish()
 
@@ -1675,9 +1675,10 @@ def test_hiveserver2_get_security():
   prev = hive_site._HIVE_SITE_DICT.get(hive_site._CNF_HIVESERVER2_AUTHENTICATION)
   try:
     hive_site._HIVE_SITE_DICT[hive_site._CNF_HIVESERVER2_AUTHENTICATION] = 'NOSASL'
-    assert_equal((False, 'NOSASL', 'hue'), HiveServerClient.get_security(beeswax_query_server))
+    hive_site._HIVE_SITE_DICT[hive_site._CNF_HIVESERVER2_IMPERSONATION] = 'true'
+    assert_equal((False, 'NOSASL', 'hue', True), HiveServerClient.get_security(beeswax_query_server))
     hive_site._HIVE_SITE_DICT[hive_site._CNF_HIVESERVER2_AUTHENTICATION] = 'KERBEROS'
-    assert_equal((True, 'GSSAPI', 'hue'), HiveServerClient.get_security(beeswax_query_server))
+    assert_equal((True, 'GSSAPI', 'hue', True), HiveServerClient.get_security(beeswax_query_server))
   finally:
     if prev is not None:
       hive_site._HIVE_SITE_DICT[hive_site._CNF_HIVESERVER2_AUTHENTICATION] = prev
@@ -1688,7 +1689,7 @@ def test_hiveserver2_get_security():
 def hive_site_xml(is_local=False, use_sasl=False, thrift_uris='thrift://darkside-1234:9999',
                   warehouse_dir='/abc', kerberos_principal='test/test.com@TEST.COM',
                   hs2_kerberos_principal='hs2test/test.com@TEST.COM',
-                  hs2_kauthentication='NOSASL'):
+                  hs2_authentication='NOSASL', hs2_impersonation='false'):
   if not is_local:
     uris = """
        <property>
@@ -1717,9 +1718,14 @@ def hive_site_xml(is_local=False, use_sasl=False, thrift_uris='thrift://darkside
         <value>%(hs2_kerberos_principal)s</value>
       </property>
 
+      <property>
+        <name>hive.server2.allow.user.substitution</name>
+        <value>%(hs2_impersonation)s</value>
+      </property>
+
       <property>
         <name>hive.metastore.sasl.enabled</name>
-        <value>%(hs2_kauthentication)s</value>
+        <value>%(hs2_authentication)s</value>
       </property>
 
       <property>
@@ -1732,6 +1738,7 @@ def hive_site_xml(is_local=False, use_sasl=False, thrift_uris='thrift://darkside
     'warehouse_dir': warehouse_dir,
     'kerberos_principal': kerberos_principal,
     'hs2_kerberos_principal': hs2_kerberos_principal,
-    'hs2_kauthentication': hs2_kauthentication,
-    'use_sasl': str(use_sasl).lower()
+    'hs2_authentication': hs2_authentication,
+    'use_sasl': str(use_sasl).lower(),
+    'hs2_impersonation': hs2_impersonation,
   }