Explorar o código

HUE-1045 [beeswax] Beeswax host selection sasl

Beeswax should choose the hostname provided as the instance component
of the hive kerberos principal when communicating to the metastore.
Abraham Elmahrek %!s(int64=12) %!d(string=hai) anos
pai
achega
fa4c985

+ 12 - 12
apps/beeswax/src/beeswax/hive_site.py

@@ -23,6 +23,8 @@ import logging
 import os.path
 import re
 
+from desktop.lib import security_util
+
 import beeswax.conf
 from hadoop import confparse
 
@@ -57,7 +59,6 @@ def get_conf():
     _parse_hive_site()
   return _HIVE_SITE_DICT
 
-
 def get_metastore():
   """
   get_metastore() -> (is_local, host, port, kerberos_principal)
@@ -71,23 +72,22 @@ def get_metastore():
   """
   global _METASTORE_LOC_CACHE
   if not _METASTORE_LOC_CACHE:
-    is_local = get_conf().getbool(_CNF_METASTORE_LOCAL, True)
-    kerberos_principal = get_conf().get(_CNF_METASTORE_KERBEROS_PRINCIPAL, None)
+    kerberos_principal = security_util.get_kerberos_principal(get_conf().get(_CNF_METASTORE_KERBEROS_PRINCIPAL, None))
+    kerberos_principal_components = security_util.get_components(kerberos_principal)
+    thrift_uri = get_conf().get(_CNF_METASTORE_URIS)
+    is_local = thrift_uri is None or thrift_uri == ''
     if is_local:
       host = beeswax.conf.BEESWAX_META_SERVER_HOST.get()
       port = beeswax.conf.BEESWAX_META_SERVER_PORT.get()
     else:
-      thrift_uri = get_conf().get(_CNF_METASTORE_URIS)
       host, port = 'undefined', '0'
-      if thrift_uri is None:
-        LOG.fatal('Remote metastore uri ("%s") not found in hive config %s' %
-                  (_CNF_METASTORE_URIS, _HIVE_SITE_PATH))
+      match = _THRIFT_URI_RE.match(thrift_uri)
+      if not match:
+        LOG.fatal('Cannot understand remote metastore uri "%s"' % (thrift_uri,))
       else:
-        match = _THRIFT_URI_RE.match(thrift_uri)
-        if not match:
-          LOG.fatal('Cannot understand remote metastore uri "%s"' % (thrift_uri,))
-        else:
-          host, port = match.groups()
+        host, port = match.groups()
+      if len(kerberos_principal_components) == 3:
+        host = kerberos_principal_components[1]
     _METASTORE_LOC_CACHE = (is_local, host, int(port), kerberos_principal)
   return _METASTORE_LOC_CACHE
 

+ 1 - 1
apps/beeswax/src/beeswax/server/beeswax_lib.py

@@ -383,9 +383,9 @@ class BeeswaxClient:
         self._encode_partition(new_part)
         return self._client.alter_partition(db_name, tbl_name, new_part)
 
+    # Use service name from kerberos principal set in hive-site.xml
     _, host, port, metastore_kerberos_principal = hive_site.get_metastore()
     use_sasl, kerberos_principal_short_name = BeeswaxClient.get_security()
-    # Use service name from kerberos principal set in hive-site.xml
     kerberos_principal_short_name = metastore_kerberos_principal and metastore_kerberos_principal.split('/', 1)[0] or None
     client = thrift_util.get_client(ThriftHiveMetastore.Client,
                                     host,

+ 48 - 0
desktop/core/src/desktop/lib/security_util.py

@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+# Licensed to Cloudera, Inc. under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  Cloudera, Inc. 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.
+
+import re
+import socket
+
+# Pattern to replace with hostname
+HOSTNAME_PATTERN = '_HOST'
+
+
+def get_kerberos_principal(principal, host=None):
+  components = get_components(principal)
+  if not components or len(components) != 3 or components[1] != HOSTNAME_PATTERN:
+    return principal
+
+
+def get_components(principal):
+  """
+  get_components(principal) -> (short name, instance (FQDN), realm)
+
+  ``principal`` is the kerberos principal to parse.
+  """
+  if not principal:
+    return None
+  return re.split('[\/@]', str(principal))
+
+def replace_hostname_pattern(components, host):
+  fqdn = host
+  if not fqdn or fqdn == '0.0.0.0':
+    fqdn = get_localhost_name()
+  return '%s/%s@%s' % (components[0], fqdn.lowercase(), components[2])
+
+def get_localhost_name():
+  return socket.get_localhost()

+ 0 - 0
desktop/core/src/desktop/lib/security_util_test.py