def _import_ldap_user(username, import_by_dn=False): """ 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. """ conn = ldap_access.get_connection() user_info = conn.find_user(username, import_by_dn) if user_info is None: LOG.warn("Could not get LDAP details for user %s" % (username,)) return None user, created = User.objects.get_or_create(username=user_info['username']) profile = get_profile(user) if not created and profile.creation_method == str(UserProfile.CreationMethod.HUE): # This is a Hue user, and shouldn't be overwritten LOG.warn('There was a naming conflict while importing user %s' % (username,)) return None default_group = get_default_user_group() if created and default_group is not None: user.groups.add(default_group) if 'first' in user_info: user.first_name = user_info['first'] if 'last' in user_info: user.last_name = user_info['last'] if 'email' in user_info: user.email = user_info['email'] profile.creation_method = UserProfile.CreationMethod.EXTERNAL profile.save() user.save() return user
def _import_ldap_nested_groups(groupname_pattern, import_members=False, recursive_import_members=False, sync_users=True, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. This will use nested groups logic. A nested group is a group that is a member of another group. e.g. CN=subtest,OU=groups,DC=exampe,DC=COM is a member of CN=test,OU=groups,DC=exampe,DC=COM and they both of the object class "groupOfNames" (or some other object class for groups). """ conn = ldap_access.get_connection() if import_by_dn: scope = ldap.SCOPE_BASE else: scope = ldap.SCOPE_SUBTREE group_info = conn.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope) if not group_info: LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn( _('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s' ) % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() # Find members and posix members for group and subgoups # Import users and groups max_count = recursive_import_members and desktop.conf.LDAP.NESTED_MEMBERS_SEARCH_DEPTH.get( ) or 1 if import_members: _import_ldap_members(conn, group, ldap_info, max_count=max_count) # Sync users if sync_users: _sync_ldap_members(conn, group, ldap_info, max_count=max_count) group.save() groups.append(group) return groups
def _import_ldap_groups(groupname_pattern, import_members=False, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() group_info = conn.find_groups(groupname_pattern, import_by_dn) if not group_info: LOG.warn(_("Could not get LDAP details for group pattern %s") % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn(_('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s') % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() for member in ldap_info['members']: users = [] if import_members: LOG.debug(_("Importing user %s") % member) users = _import_ldap_users(member, import_by_dn=True) else: user_info = conn.find_users(member, find_by_dn=True) if len(user_info) > 1: LOG.warn(_('Found multiple users for member %s.') % member) else: for ldap_info in user_info: try: user = User.objects.get(username=ldap_info['username']) except User.DoesNotExist: continue users.append(user) if not users: # There was a naming conflict, or for some other reason, we couldn't get # at the user continue LOG.debug(_("Adding member %s represented as users (should be a single user) %s to group %s") % (member, str(users), group.name)) for user in users: group.user_set.add(user) group.save() groups.append(group) return groups
def _import_ldap_users_info(user_info, sync_groups=False, import_by_dn=False): """ Import user_info found through ldap_access.find_users. """ imported_users = [] for ldap_info in user_info: user, created = ldap_access.get_or_create_ldap_user(username=ldap_info['username']) profile = get_profile(user) if not created and profile.creation_method == str(UserProfile.CreationMethod.HUE): # This is a Hue user, and shouldn't be overwritten LOG.warn(_('There was a naming conflict while importing user %(username)s') % { 'username': ldap_info['username'] }) return None default_group = get_default_user_group() if created and default_group is not None: user.groups.add(default_group) if 'first' in ldap_info: user.first_name = ldap_info['first'] if 'last' in ldap_info: user.last_name = ldap_info['last'] if 'email' in ldap_info: user.email = ldap_info['email'] profile.creation_method = UserProfile.CreationMethod.EXTERNAL profile.save() user.save() imported_users.append(user) # sync groups if sync_groups and 'groups' in ldap_info: conn = ldap_access.get_connection() old_groups = set(user.groups.all()) new_groups = set() # Skip if 'memberOf' or 'isMemberOf' are not set for group_dn in ldap_info['groups']: group_ldap_info = conn.find_groups(group_dn, find_by_dn=True, scope=ldap.SCOPE_BASE) for group_info in group_ldap_info: # Add only if user isn't part of group. if not user.groups.filter(name=group_info['name']).exists(): groups = import_ldap_groups(group_info['dn'], import_members=False, import_members_recursive=False, sync_users=False, import_by_dn=True) if groups: new_groups.update(groups) # Remove out of date groups remove_groups = old_groups - new_groups remove_ldap_groups = LdapGroup.objects.filter(group__in=remove_groups) remove_groups_filtered = [ldapgroup.group for ldapgroup in remove_ldap_groups] user.groups.filter(group__in=remove_groups_filtered).delete() user.groups.add(*new_groups) Group.objects.filter(group__in=remove_groups_filtered).delete() remove_ldap_groups.delete() return imported_users
def _import_ldap_users(username_pattern, sync_groups=False, import_by_dn=False): """ 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. """ conn = ldap_access.get_connection() user_info = conn.find_users(username_pattern, find_by_dn=import_by_dn) if not user_info: LOG.warn("Could not get LDAP details for users with pattern %s" % username_pattern) return None return _import_ldap_users_info(user_info, sync_groups, import_by_dn)
def _import_ldap_nested_groups(groupname_pattern, import_members=False, recursive_import_members=False, sync_users=True, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. This will use nested groups logic. A nested group is a group that is a member of another group. e.g. CN=subtest,OU=groups,DC=exampe,DC=COM is a member of CN=test,OU=groups,DC=exampe,DC=COM and they both of the object class "groupOfNames" (or some other object class for groups). """ conn = ldap_access.get_connection() if import_by_dn: scope = ldap.SCOPE_BASE else: scope = ldap.SCOPE_SUBTREE group_info = conn.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope) if not group_info: LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn(_('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s') % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() # Find members and posix members for group and subgoups # Import users and groups max_count = recursive_import_members and desktop.conf.LDAP.NESTED_MEMBERS_SEARCH_DEPTH.get() or 1 if import_members: _import_ldap_members(conn, group, ldap_info, max_count=max_count) # Sync users if sync_users: _sync_ldap_members(conn, group, ldap_info, max_count=max_count) group.save() groups.append(group) return groups
def _import_ldap_group(groupname, import_members=False, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() group_info = conn.find_group(groupname, import_by_dn) if group_info is None: LOG.warn("Could not get LDAP details for group %s" % (groupname, )) return None group, created = Group.objects.get_or_create(name=group_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn('There was a naming conflict while importing group %s' % (groupname, )) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() for member in group_info['members']: if import_members: LOG.debug("Importing user %s" % (member, )) user = _import_ldap_user(member, import_by_dn=True) else: user_info = conn.find_user(member, find_by_dn=True) try: user = User.objects.get(username=user_info['username']) except User.DoesNotExist: continue if user is None: # There was a naming conflict, or for some other reason, we couldn't get # at the user continue LOG.debug("Adding user %s to group %s" % (member, group.name)) group.user_set.add(user) group.save() return group
def _import_ldap_group(groupname, import_members=False, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() group_info = conn.find_group(groupname, import_by_dn) if group_info is None: LOG.warn("Could not get LDAP details for group %s" % (groupname,)) return None group, created = Group.objects.get_or_create(name=group_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn('There was a naming conflict while importing group %s' % (groupname,)) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() for member in group_info['members']: if import_members: LOG.debug("Importing user %s" % (member,)) user = _import_ldap_user(member, import_by_dn=True) else: user_info = conn.find_user(member, find_by_dn=True) try: user = User.objects.get(username=user_info['username']) except User.DoesNotExist: continue if user is None: # There was a naming conflict, or for some other reason, we couldn't get # at the user continue LOG.debug("Adding user %s to group %s" % (member, group.name)) group.user_set.add(user) group.save() return group
def _import_ldap_groups(groupname_pattern, import_members=False, recursive_import_members=False, sync_users=True, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() if import_by_dn: scope = ldap.SCOPE_BASE else: scope = ldap.SCOPE_SUBTREE group_info = conn.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope) if not group_info: LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn( _('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s' ) % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() # Find members and posix members for group and subgoups members = ldap_info['members'] posix_members = ldap_info['posix_members'] if recursive_import_members: sub_group_info = conn.find_groups(ldap_info['dn'], find_by_dn=True) for sub_ldap_info in sub_group_info: members.extend(sub_ldap_info['members']) posix_members.extend(sub_ldap_info['posix_members']) # Import/fetch users for member in members: users = [] if import_members: LOG.debug("Importing user %s" % str(member)) users = _import_ldap_users(member, import_by_dn=True) elif sync_users: user_info = conn.find_users(member, find_by_dn=True) if len(user_info) > 1: LOG.warn('Found multiple users for member %s.' % member) else: for ldap_info in user_info: try: user = User.objects.get( username=ldap_info['username']) users.append(user) except User.DoesNotExist: pass if users: LOG.debug( "Adding member %s represented as users (should be a single user) %s to group %s" % (str(member), str(users), str(group.name))) group.user_set.add(*users) # Import/fetch posix users for posix_member in posix_members: users = [] if import_members: LOG.debug("Importing user %s" % str(posix_member)) # posixGroup class defines 'memberUid' to be login names, # which are defined by 'uid'. user_info = conn.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(user_info, import_by_dn=False) elif sync_users: user_info = conn.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP. USERS.USER_NAME_ATTR.get(), find_by_dn=False) if len(user_info) > 1: LOG.warn('Found multiple users for member %s.' % member) else: for ldap_info in user_info: try: user = User.objects.get( username=ldap_info['username']) users.append(user) except User.DoesNotExist: pass 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) group.save() groups.append(group) return groups
def _import_ldap_groups(groupname_pattern, import_members=False, recursive_import_members=False, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() group_info = conn.find_groups(groupname_pattern, import_by_dn) if not group_info: LOG.warn( _("Could not get LDAP details for group pattern %s") % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn( _('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s' ) % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() # Find members for group and subgoups members = ldap_info['members'] if recursive_import_members: sub_group_info = conn.find_groups(ldap_info['dn'], True) for sub_ldap_info in sub_group_info: members.extend(sub_ldap_info['members']) # Import/fetch users for member in members: users = [] if import_members: LOG.debug(_("Importing user %s") % member) users = _import_ldap_users(member, import_by_dn=True) else: user_info = conn.find_users(member, find_by_dn=True) if len(user_info) > 1: LOG.warn(_('Found multiple users for member %s.') % member) else: for ldap_info in user_info: try: user = User.objects.get( username=ldap_info['username']) except User.DoesNotExist: continue users.append(user) if not users: # There was a naming conflict, or for some other reason, we couldn't get # at the user continue LOG.debug( _("Adding member %s represented as users (should be a single user) %s to group %s" ) % (member, str(users), group.name)) for user in users: group.user_set.add(user) group.save() groups.append(group) return groups
def _import_ldap_groups(groupname_pattern, import_members=False, recursive_import_members=False, sync_users=True, import_by_dn=False): """ Import a group from LDAP. If import_members is true, this will also import any LDAP users that exist within the group. """ conn = ldap_access.get_connection() if import_by_dn: scope = ldap.SCOPE_BASE else: scope = ldap.SCOPE_SUBTREE group_info = conn.find_groups(groupname_pattern, find_by_dn=import_by_dn, scope=scope) if not group_info: LOG.warn("Could not get LDAP details for group pattern %s" % groupname_pattern) return None groups = [] for ldap_info in group_info: group, created = Group.objects.get_or_create(name=ldap_info['name']) if not created and not LdapGroup.objects.filter(group=group).exists(): # This is a Hue group, and shouldn't be overwritten LOG.warn(_('There was a naming conflict while importing group %(groupname)s in pattern %(groupname_pattern)s') % { 'groupname': ldap_info['name'], 'groupname_pattern': groupname_pattern }) return None LdapGroup.objects.get_or_create(group=group) group.user_set.clear() # Find members and posix members for group and subgoups members = ldap_info['members'] posix_members = ldap_info['posix_members'] if recursive_import_members: sub_group_info = conn.find_groups(ldap_info['dn'], find_by_dn=True) for sub_ldap_info in sub_group_info: members.extend(sub_ldap_info['members']) posix_members.extend(sub_ldap_info['posix_members']) # Import/fetch users for member in members: users = [] if import_members: LOG.debug("Importing user %s" % str(member)) users = _import_ldap_users(member, import_by_dn=True) elif sync_users: user_info = conn.find_users(member, find_by_dn=True) if len(user_info) > 1: LOG.warn('Found multiple users for member %s.' % member) else: for ldap_info in user_info: try: user = ldap_access.get_ldap_user(username=ldap_info['username']) users.append(user) except User.DoesNotExist: pass if users: LOG.debug("Adding member %s represented as users (should be a single user) %s to group %s" % (str(member), str(users), str(group.name))) group.user_set.add(*users) # Import/fetch posix users for posix_member in posix_members: users = [] if import_members: LOG.debug("Importing user %s" % str(posix_member)) # posixGroup class defines 'memberUid' to be login names, # which are defined by 'uid'. user_info = conn.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(user_info, import_by_dn=False) elif sync_users: user_info = conn.find_users(posix_member, search_attr='uid', user_name_attr=desktop.conf.LDAP.USERS.USER_NAME_ATTR.get(), find_by_dn=False) if len(user_info) > 1: LOG.warn('Found multiple users for member %s.' % member) else: for ldap_info in user_info: try: user = ldap_access.get_ldap_user(username=ldap_info['username']) users.append(user) except User.DoesNotExist: pass 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) group.save() groups.append(group) return groups