Browse Source

HUE-8420 [core] Add option to limit login to list of ldap groups

(cherry picked from commit 67658dcd261ab06b14d80d32074ecea39da6e936)
Chris Conner 7 years ago
parent
commit
fa56efb757

+ 29 - 19
apps/useradmin/src/useradmin/views.py

@@ -759,6 +759,10 @@ def import_ldap_groups(connection, group_pattern, import_members, import_members
                              import_by_dn, failed_users=failed_users)
 
 
+def get_find_groups_filter(ldap_info):
+  return _get_find_groups_filter(ldap_info)
+
+
 def sync_ldap_users(connection, failed_users=None):
   """
   Syncs LDAP user information. This will not import new
@@ -804,7 +808,6 @@ def ensure_home_directory(fs, user):
   else:
     LOG.warn("Not creating home directory of %s as his profile is empty" % user)
 
-
 def sync_unix_users_and_groups(min_uid, max_uid, min_gid, max_gid, check_shell):
   """
   Syncs the Hue database with the underlying Unix system, by importing users and
@@ -899,6 +902,30 @@ def _import_ldap_users(connection, username_pattern, sync_groups=False, import_b
   return _import_ldap_users_info(connection, user_info, sync_groups, import_by_dn, server, failed_users=failed_users)
 
 
+def _get_find_groups_filter(ldap_info):
+  if desktop.conf.LDAP.LDAP_SERVERS.get():
+    # Choose from multiple server configs
+    ldap_config = desktop.conf.LDAP.LDAP_SERVERS.get()[server]
+  else:
+    ldap_config = desktop.conf.LDAP
+
+  group_member_attr = ldap_config.GROUPS.GROUP_MEMBER_ATTR.get()
+  group_filter = ldap_config.GROUPS.GROUP_FILTER.get()
+  # Search for groups based on group_member_attr=username and group_member_attr=dn
+  # covers AD, Standard Ldap and posixAcount/posixGroup
+  if not group_filter.startswith('('):
+    group_filter = '(' + group_filter + ')'
+
+  # Sanitizing the DN before using in a Search filter
+  sanitized_dn = ldap.filter.escape_filter_chars(ldap_info['dn']).replace(r'\2a', r'*')
+  sanitized_dn = sanitized_dn.replace(r'\5c,', r'\5c\2c')
+
+  find_groups_filter = "(&" + group_filter + "(|(" + group_member_attr + "=" + ldap_info['username'] + ")(" + \
+                       group_member_attr + "=" + sanitized_dn + ")))"
+
+  return find_groups_filter
+
+
 def _import_ldap_users_info(connection, user_info, sync_groups=False, import_by_dn=False, server=None, failed_users=None):
   """
   Import user_info found through ldap_access.find_users.
@@ -943,25 +970,8 @@ def _import_ldap_users_info(connection, user_info, sync_groups=False, import_by_
         new_groups = set()
         current_ldap_groups = set()
 
-        if desktop.conf.LDAP.LDAP_SERVERS.get():
-          # Choose from multiple server configs
-          ldap_config = desktop.conf.LDAP.LDAP_SERVERS.get()[server]
-        else:
-          ldap_config = desktop.conf.LDAP
-
-        group_member_attr = ldap_config.GROUPS.GROUP_MEMBER_ATTR.get()
-        group_filter = ldap_config.GROUPS.GROUP_FILTER.get()
-        # Search for groups based on group_member_attr=username and group_member_attr=dn
-        # covers AD, Standard Ldap and posixAcount/posixGroup
-        if not group_filter.startswith('('):
-          group_filter = '(' + group_filter + ')'
-
-        # Sanitizing the DN before using in a Search filter
-        sanitized_dn = ldap.filter.escape_filter_chars(ldap_info['dn']).replace(r'\2a', r'*')
-        sanitized_dn = sanitized_dn.replace(r'\5c,', r'\5c\2c')
+        find_groups_filter = _get_find_groups_filter(ldap_info)
 
-        find_groups_filter = "(&" + group_filter + "(|(" + group_member_attr + "=" + ldap_info['username'] + ")(" + \
-                             group_member_attr + "=" + sanitized_dn + ")))"
         group_ldap_info = connection.find_groups("*", group_filter=find_groups_filter)
         for group_info in group_ldap_info:
           if Group.objects.filter(name=group_info['name']).exists():

+ 34 - 2
desktop/core/src/desktop/auth/backend.py

@@ -55,7 +55,7 @@ from mozilla_django_oidc.utils import absolutify, import_from_settings
 from useradmin import ldap_access
 from useradmin.forms import validate_username
 from useradmin.models import get_profile, get_default_user_group, UserProfile
-from useradmin.views import import_ldap_users
+from useradmin.views import import_ldap_users, get_find_groups_filter
 
 
 LOG = logging.getLogger(__name__)
@@ -467,7 +467,12 @@ class LdapBackend(object):
       return None
 
     try:
-      user = self._backend.authenticate(username, password)
+      allowed_group = self.check_ldap_access_groups(server, username)
+      if allowed_group:
+        user = self._backend.authenticate(username, password)
+      else:
+        LOG.warn("%s not in an allowed login group" % username)
+        return None
     except ImproperlyConfigured, detail:
       LOG.warn("LDAP was not properly configured: %s", detail)
       return None
@@ -491,6 +496,33 @@ class LdapBackend(object):
     user = rewrite_user(user)
     return user
 
+  def check_ldap_access_groups(self, server, username):
+    allowed_group = False
+
+    if desktop.conf.LDAP.LOGIN_GROUPS.get() and desktop.conf.LDAP.LOGIN_GROUPS.get() != ['']:
+      login_groups = desktop.conf.LDAP.LOGIN_GROUPS.get()
+      connection = ldap_access.get_connection_from_server(server)
+      try:
+        user_info = connection.find_users(username, find_by_dn=False)
+      except LdapSearchException, e:
+        LOG.warn("Failed to find LDAP user: %s" % e)
+
+      if not user_info:
+        LOG.warn("Could not get LDAP details for users with pattern %s" % username_pattern)
+        return None
+
+      ldap_info = user_info[0]
+      group_ldap_info = connection.find_groups("*", group_filter=get_find_groups_filter(ldap_info))
+      for group in group_ldap_info:
+        if group['name'] in login_groups:
+          allowed_group = True
+
+    else:
+      #Login groups not set default to True
+      allowed_group = True
+
+    return allowed_group
+
   def import_groups(self, server, user):
     connection = ldap_access.get_connection_from_server(server)
     import_ldap_users(connection, user.username, sync_groups=True, import_by_dn=False, server=server)

+ 4 - 1
desktop/core/src/desktop/conf.py

@@ -1037,7 +1037,10 @@ LDAP = ConfigSection(
       help=_("Whether or not to follow referrals."),
       type=coerce_bool,
       default=False),
-
+    LOGIN_GROUPS = Config("login_groups",
+      help=_("Define a list of Ldap groups in CSV with users that can login"),
+      type=coerce_csv,
+      default=[]),
     DEBUG = Config("debug",
       type=coerce_bool,
       default=False,