Преглед на файлове

[security] Kerberos support

Romain Rigaux преди 11 години
родител
ревизия
c0c1a20

+ 1 - 1
desktop/core/src/desktop/lib/thrift_util.py

@@ -75,7 +75,7 @@ class ConnectionConfig(object):
                kerberos_principal="thrift",
                mechanism='GSSAPI',
                username='hue',
-	       password='hue',
+	             password='hue',
                ca_certs=None,
                keyfile=None,
                certfile=None,

+ 28 - 3
desktop/libs/libsentry/src/libsentry/client.py

@@ -25,6 +25,9 @@ from sentry_policy_service.ttypes import TListSentryRolesRequest, TListSentryPri
     TAlterSentryRoleRevokePrivilegeRequest, TAlterSentryRoleAddGroupsRequest, TSentryGroup, TAlterSentryRoleDeleteGroupsRequest, \
     TListSentryPrivilegesForProviderRequest, TSentryActiveRoleSet, TSentryAuthorizable, TDropPrivilegesRequest, TRenamePrivilegesRequest
 
+from libsentry.sentry_site import get_sentry_server_authentication,\
+  get_sentry_server_principal
+
 
 LOG = logging.getLogger(__name__)
 
@@ -50,20 +53,42 @@ struct TSentryAuthorizable {
 """
 
 class SentryClient(object):
+  SENTRY_MECHANISMS = {'KERBEROS': 'GSSAPI', 'NOSASL': 'NOSASL'}
 
   def __init__(self, host, port, username):
     self.username = username
-
-    self.client = thrift_util.get_client( # TODO: kerberos
+    self.security = self._get_security()
+    
+    self.client = thrift_util.get_client(
         SentryPolicyService.Client,
         host,
         port,
         service_name="SentryPolicyService",
         username=self.username,
         timeout_seconds=30,
-        multiple=True
+        multiple=True,
+        kerberos_principal=self.security['kerberos_principal_short_name'],
+        use_sasl=self.security['use_sasl'],
+        mechanism=self.security['mechanism']
     )
 
+
+  def _get_security(self):
+    principal = get_sentry_server_principal()
+    if principal:
+      kerberos_principal_short_name = principal.split('/', 1)[0]
+    else:
+      kerberos_principal_short_name = None
+    use_sasl = get_sentry_server_authentication() == 'KERBEROS'
+    mechanism = SentryClient.SENTRY_MECHANISMS[get_sentry_server_authentication()]
+    
+    return {
+        'kerberos_principal_short_name': kerberos_principal_short_name,
+        'use_sasl': use_sasl,
+        'mechanism': mechanism
+    }
+
+
   def create_sentry_role(self, roleName):
     request = TCreateSentryRoleRequest(requestorUserName=self.username, roleName=roleName)
     return self.client.create_sentry_role(request)

+ 16 - 1
desktop/libs/libsentry/src/libsentry/sentry_site.py

@@ -20,8 +20,9 @@ import logging
 import os.path
 
 from hadoop import confparse
+from desktop.lib import security_util
 
-from libsentry.conf import SENTRY_CONF_DIR
+from libsentry.conf import SENTRY_CONF_DIR, HOSTNAME
 
 
 LOG = logging.getLogger(__name__)
@@ -31,6 +32,8 @@ _SENTRY_SITE_PATH = None
 _SENTRY_SITE_DICT = None
 
 _CONF_HIVE_PROVIDER = 'hive.sentry.provider'
+_CONF_SENTRY_SERVER_PRINCIPAL = 'sentry.service.server.principal'
+_CONF_SENTRY_SERVER_SECURITY_MODE = 'sentry.service.security.mode'
 
 
 def reset():
@@ -48,6 +51,18 @@ def get_conf():
 def get_hive_sentry_provider():
   return get_conf().get(_CONF_HIVE_PROVIDER, 'default')
 
+def get_sentry_server_principal():  
+  # Get kerberos principal and replace host pattern
+  principal = get_conf().get(_CONF_SENTRY_SERVER_PRINCIPAL, None)
+  if principal:
+    fqdn = security_util.get_fqdn(HOSTNAME.get())
+    return security_util.get_kerberos_principal(principal, fqdn)
+  else:
+    return None
+
+def get_sentry_server_authentication():
+  return get_conf().get(_CONF_SENTRY_SERVER_SECURITY_MODE, 'NOSASL').upper()
+
 
 def _parse_site():
   global _SENTRY_SITE_DICT

+ 102 - 0
desktop/libs/libsentry/src/libsentry/test_client.py

@@ -0,0 +1,102 @@
+#!/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 os
+import shutil
+import tempfile
+
+from nose.tools import assert_true, assert_equal, assert_false, assert_not_equal, assert_raises
+
+from libsentry import sentry_site
+from libsentry.conf import SENTRY_CONF_DIR
+from libsentry.sentry_site import get_hive_sentry_provider,\
+  get_sentry_server_principal
+from libsentry.client import SentryClient
+
+
+
+def test_security_plain():
+  tmpdir = tempfile.mkdtemp()
+  finish = SENTRY_CONF_DIR.set_for_testing(tmpdir)
+
+  try:
+    xml = sentry_site_xml(provider='default')
+    file(os.path.join(tmpdir, 'sentry-site.xml'), 'w').write(xml)
+    sentry_site.reset()
+
+    assert_equal('default', get_hive_sentry_provider())
+    assert_equal('test/test.com@TEST.COM', get_sentry_server_principal())
+
+    security = SentryClient('test.com', 11111, 'test')._get_security()
+
+    assert_equal('test', security['kerberos_principal_short_name'])
+    assert_equal(False, security['use_sasl'])
+    assert_equal('NOSASL', security['mechanism'])
+  finally:
+    sentry_site.reset()
+    finish()
+    shutil.rmtree(tmpdir)
+
+
+def test_security_kerberos():
+  tmpdir = tempfile.mkdtemp()
+  finish = SENTRY_CONF_DIR.set_for_testing(tmpdir)
+
+  try:
+    xml = sentry_site_xml(provider='default', authentication='kerberos')
+    file(os.path.join(tmpdir, 'sentry-site.xml'), 'w').write(xml)
+    sentry_site.reset()
+
+    security = SentryClient('test.com', 11111, 'test')._get_security()
+
+    assert_equal(True, security['use_sasl'])
+    assert_equal('GSSAPI', security['mechanism'])
+  finally:
+    sentry_site.reset()
+    finish()
+    shutil.rmtree(tmpdir)
+
+
+def sentry_site_xml(
+    provider='default',
+    kerberos_principal='test/test.com@TEST.COM',
+    authentication='NOSASL'):
+
+  return """
+    <configuration>
+
+      <property>
+        <name>hive.sentry.provider</name>
+        <value>%(provider)s</value>
+      </property>
+
+      <property>
+        <name>sentry.service.server.principal</name>
+        <value>%(kerberos_principal)s</value>
+      </property>
+
+      <property>
+        <name>sentry.service.security.mode</name>
+        <value>%(authentication)s</value>
+      </property>
+
+    </configuration>
+  """ % {
+    'provider': provider,
+    'kerberos_principal': kerberos_principal,
+    'authentication': authentication,
+  }