Преглед изворни кода

[useradmin] LDAP group sync: Do not fail when members exist outside of current domain

Jenny Kim пре 10 година
родитељ
комит
c74f64f
2 измењених фајлова са 104 додато и 29 уклоњено
  1. 11 3
      apps/useradmin/src/useradmin/ldap_access.py
  2. 93 26
      apps/useradmin/src/useradmin/views.py

+ 11 - 3
apps/useradmin/src/useradmin/ldap_access.py

@@ -34,6 +34,14 @@ LOG = logging.getLogger(__name__)
 CACHED_LDAP_CONN = None
 
 
+class LdapBindException(Exception):
+  pass
+
+
+class LdapSearchException(Exception):
+  pass
+
+
 def get_connection_from_server(server=None):
 
   ldap_servers = desktop.conf.LDAP.LDAP_SERVERS.get()
@@ -129,7 +137,7 @@ class LdapConnection(object):
       except:
         msg = "Failed to bind to LDAP server as user %s" % bind_user
         LOG.exception(msg)
-        raise RuntimeError(msg)
+        raise LdapBindException(msg)
     else:
       try:
         # Do anonymous bind
@@ -137,7 +145,7 @@ class LdapConnection(object):
       except:
         msg = "Failed to bind to LDAP server anonymously"
         LOG.exception(msg)
-        raise RuntimeError(msg)
+        raise LdapBindException(msg)
 
   def _get_search_params(self, name, attr, find_by_dn=False):
     """
@@ -150,7 +158,7 @@ class LdapConnection(object):
       search_dn = re.sub(r'(\w+=)', lambda match: match.group(0).upper(), name)
 
       if not search_dn.upper().endswith(base_dn.upper()):
-        raise RuntimeError("Distinguished Name provided does not contain configured Base DN. Base DN: %(base_dn)s, DN: %(dn)s" % {
+        raise LdapSearchException("Distinguished Name provided does not contain configured Base DN. Base DN: %(base_dn)s, DN: %(dn)s" % {
           'base_dn': base_dn,
           'dn': search_dn
         })

+ 93 - 26
apps/useradmin/src/useradmin/views.py

@@ -24,6 +24,7 @@ import json
 
 import ldap
 import ldap_access
+from ldap_access import LdapSearchException
 
 from django.contrib.auth.models import User, Group
 
@@ -355,7 +356,7 @@ def add_ldap_users(request):
       except ldap.LDAPError, e:
         LOG.error("LDAP Exception: %s" % e)
         raise PopupException(_('There was an error when communicating with LDAP'), detail=str(e))
-      except (AssertionError, RuntimeError), e:
+      except AssertionError, e:
         raise PopupException(_('There was a problem with some of the LDAP information'), detail=str(e))
 
       if users and form.cleaned_data['ensure_home_directory']:
@@ -407,7 +408,7 @@ def add_ldap_groups(request):
       except ldap.LDAPError, e:
         LOG.error(_("LDAP Exception: %s") % e)
         raise PopupException(_('There was an error when communicating with LDAP'), detail=str(e))
-      except (AssertionError, RuntimeError), e:
+      except AssertionError, e:
         raise PopupException(_('There was a problem with some of the LDAP information'), detail=str(e))
 
       unique_users = set()
@@ -600,7 +601,12 @@ def _import_ldap_users(connection, username_pattern, sync_groups=False, import_b
   Import a user from LDAP. If import_by_dn is true, this will import the user by
   the distinguished name, rather than the configured username attribute.
   """
-  user_info = connection.find_users(username_pattern, find_by_dn=import_by_dn)
+  user_info = None
+  try:
+    user_info = connection.find_users(username_pattern, find_by_dn=import_by_dn)
+  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
@@ -681,7 +687,7 @@ def _import_ldap_users_info(connection, user_info, sync_groups=False, import_by_
           user.groups.remove(group)
         user.groups.add(*new_groups)
         Group.objects.filter(group__in=remove_groups_filtered).delete()
-    except (AssertionError, RuntimeError) as e:
+    except (AssertionError, LdapSearchException) as e:
       LOG.warn('Could not import %s: %s' % (ldap_info['username'], e.message))
 
   return imported_users
@@ -692,8 +698,18 @@ def _import_ldap_members(connection, group, ldap_info, count=0, max_count=1):
     return None
 
   # Find all users and groups of group.
-  users_info = connection.find_users_of_group(ldap_info['dn'])
-  groups_info = connection.find_groups_of_group(ldap_info['dn'])
+  uusers_info, groups_info = [], []
+
+  try:
+    users_info = connection.find_users_of_group(ldap_info['dn'])
+  except LdapSearchException, e:
+    LOG.warn("Failed to find LDAP users of group: %s" % e)
+
+  try:
+    groups_info = connection.find_groups_of_group(ldap_info['dn'])
+  except LdapSearchException, e:
+    LOG.warn("Failed to find LDAP groups of group: %s" % e)
+
   posix_members = ldap_info['posix_members']
 
   for user_info in users_info:
@@ -714,12 +730,17 @@ def _import_ldap_members(connection, group, ldap_info, count=0, max_count=1):
 
   for posix_member in posix_members:
     LOG.debug("Importing posix user %s into group %s" % (smart_str(posix_member), smart_str(group.name)))
-    user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
-    users = _import_ldap_users_info(connection, user_info)
+    user_info = None
+    try:
+      user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+    except LdapSearchException, e:
+      LOG.warn("Failed to find LDAP users: %s" % e)
 
-    if users:
-      LOG.debug("Adding member %s represented as users (should be a single user) %s to group %s" % (str(posix_member), str(users), str(group.name)))
-      group.user_set.add(*users)
+    if user_info:
+      users = _import_ldap_users_info(connection, user_info)
+      if users:
+        LOG.debug("Adding member %s represented as users (should be a single user) %s to group %s" % (str(posix_member), str(users), str(group.name)))
+        group.user_set.add(*users)
 
 
 def _sync_ldap_members(connection, group, ldap_info, count=0, max_count=1):
@@ -727,8 +748,18 @@ def _sync_ldap_members(connection, group, ldap_info, count=0, max_count=1):
     return None
 
   # Find all users and groups of group.
-  users_info = connection.find_users_of_group(ldap_info['dn'])
-  groups_info = connection.find_groups_of_group(ldap_info['dn'])
+  users_info, groups_info = [], []
+
+  try:
+    users_info = connection.find_users_of_group(ldap_info['dn'])
+  except LdapSearchException, e:
+    LOG.warn("Failed to find LDAP users of group: %s" % e)
+
+  try:
+    groups_info = connection.find_groups_of_group(ldap_info['dn'])
+  except LdapSearchException, e:
+    LOG.warn("Failed to find LDAP groups of group: %s" % e)
+
   posix_members = ldap_info['posix_members']
 
   for user_info in users_info:
@@ -750,7 +781,12 @@ def _sync_ldap_members(connection, group, ldap_info, count=0, max_count=1):
 
   for posix_member in posix_members:
     LOG.debug("Synchronizing posix user %s with group %s" % (smart_str(posix_member), smart_str(group.name)))
-    users_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+    users_info = []
+    try:
+      users_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+    except LdapSearchException, e:
+      LOG.warn("Failed to find LDAP users: %s" % e)
+
     for user_info in users_info:
       try:
         user = ldap_access.get_ldap_user(username=user_info['username'])
@@ -772,7 +808,12 @@ def _import_ldap_nested_groups(connection, groupname_pattern, import_members=Fal
     scope = ldap.SCOPE_BASE
   else:
     scope = ldap.SCOPE_SUBTREE
-  group_info = connection.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope)
+
+  group_info = None
+  try:
+    group_info = connection.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope)
+  except LdapSearchException, e:
+    LOG.warn("Failed to find LDAP group: %s" % e)
 
   if not group_info:
     LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern)
@@ -822,7 +863,12 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
     scope = ldap.SCOPE_BASE
   else:
     scope = ldap.SCOPE_SUBTREE
-  group_info = connection.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope)
+
+  group_info = None
+  try:
+    group_info = connection.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope)
+  except LdapSearchException, e:
+    LOG.warn("Could not find LDAP group: %s" % e)
 
   if not group_info:
     LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern)
@@ -849,7 +895,13 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
     # @TODO: Deprecate recursive_import_members as it may not be useful.
     if import_members:
       if recursive_import_members:
-        for sub_ldap_info in connection.find_groups(ldap_info['dn'], find_by_dn=True):
+        group_info = []
+        try:
+          group_info = connection.find_groups(ldap_info['dn'], find_by_dn=True)
+        except LdapSearchException, e:
+          LOG.warn("Failed to find LDAP group: %s" % e)
+
+        for sub_ldap_info in group_info:
           members += sub_ldap_info['members']
           posix_members += sub_ldap_info['posix_members']
 
@@ -860,7 +912,12 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
     # Sync users
     if sync_users:
       for member in members:
-        user_info = connection.find_users(member, find_by_dn=True)
+        user_info = []
+        try:
+          user_info = connection.find_users(member, find_by_dn=True)
+        except LdapSearchException, e:
+          LOG.warn("Failed to find LDAP user: %s" % e)
+
         if len(user_info) > 1:
           LOG.warn('Found multiple users for member %s.' % member)
         else:
@@ -869,7 +926,7 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
               validate_username(ldap_info['username'])
               user = ldap_access.get_ldap_user(username=ldap_info['username'])
               group.user_set.add(user)
-            except (AssertionError, RuntimeError), e:
+            except AssertionError, e:
               LOG.warn('Could not sync %s: %s' % (ldap_info['username'], e.message))
             except User.DoesNotExist:
               pass
@@ -882,16 +939,26 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
           LOG.debug("Importing user %s" % str(posix_member))
           # posixGroup class defines 'memberUid' to be login names,
           # which are defined by 'uid'.
-          user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
-          users = _import_ldap_users_info(connection, user_info, import_by_dn=False)
+          user_info = None
+          try:
+            user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+          except LdapSearchException, e:
+            LOG.warn("Failed to find LDAP user: %s" % e)
 
-          if users:
-            LOG.debug("Adding member %s represented as users (should be a single user) %s to group %s" % (str(posix_member), str(users), str(group.name)))
-            group.user_set.add(*users)
+          if user_info:
+            users = _import_ldap_users_info(connection, user_info, import_by_dn=False)
+            if users:
+              LOG.debug("Adding member %s represented as users (should be a single user) %s to group %s" % (str(posix_member), str(users), str(group.name)))
+              group.user_set.add(*users)
 
       if sync_users:
         for posix_member in posix_members:
-          user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+          user_info = []
+          try:
+            user_info = connection.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False)
+          except LdapSearchException, e:
+            LOG.warn("Failed to find LDAP user: %s" % e)
+
           if len(user_info) > 1:
             LOG.warn('Found multiple users for member %s.' % posix_member)
           else:
@@ -900,7 +967,7 @@ def _import_ldap_suboordinate_groups(connection, groupname_pattern, import_membe
                 validate_username(ldap_info['username'])
                 user = ldap_access.get_ldap_user(username=ldap_info['username'])
                 group.user_set.add(user)
-              except (AssertionError, RuntimeError), e:
+              except AssertionError, e:
                 LOG.warn('Could not sync %s: %s' % (ldap_info['username'], e.message))
               except User.DoesNotExist:
                 pass