""" This module defines `Celery`_ tasks to manage LDAP entities. .. _Celery: http://www.celeryproject.org/ """ from __future__ import absolute_import from django.core.exceptions import ObjectDoesNotExist from celery import shared_task from celery.utils.log import get_task_logger from celery.exceptions import Reject from ldapentities.models import ( LdapGroup, LdapUser, ) _LOGGER = get_task_logger(__name__) @shared_task def create_ldap_group(groupname, gid, descr): """ This task creates an :py:class:`LDAP group ` if it does not exist yet. If a group with the given name exists its group id and description attributes are updated. :param str groupname: the group name :param int gid: the group id :param str descr: description text for the group :return: the distinguished name of the group :rtype: str """ try: ldapgroup = LdapGroup.objects.get(name=groupname) _LOGGER.info( 'LDAP group %s with groupname %s already exists', ldapgroup.dn, groupname) ldapgroup.gid = gid except LdapGroup.DoesNotExist: ldapgroup = LdapGroup(gid=gid, name=groupname) _LOGGER.info('created LDAP group %s', ldapgroup.dn) ldapgroup.description = descr ldapgroup.save() _LOGGER.info('set description of LDAP group %s', ldapgroup.dn) return ldapgroup.dn @shared_task def create_ldap_user(username, uid, gid, gecos, homedir, shell, password): """ This task creates an :py:class:`LDAP user ` if it does not exist yet. The task is rejected if the primary group of the user is not defined. The user's fields are updated if the user already exists. :param str username: the user name :param int uid: the user id :param int gid: the user's primary group's id :param str gecos: the text for the GECOS field :param str homedir: the user's home directory :param str shell: the user's login shell :param str or None password: the clear text password, if :py:const:`None` is passed the password is not touched :raises celery.exceptions.Reject: if the specified primary group does not exist :return: the distinguished name of the user :rtype: str """ try: ldapuser = LdapUser.objects.get(username=username) _LOGGER.info( 'LDAP user %s with username %s already exists', ldapuser.dn, username) except LdapUser.DoesNotExist: ldapuser = LdapUser(username=username) try: ldapgroup = LdapGroup.objects.get(gid=gid) except ObjectDoesNotExist as exc: _LOGGER.error('LDAP group with gid %d does not exist', gid) raise Reject(exc, requeue=False) ldapuser.uid = uid ldapuser.group = gid ldapuser.gecos = gecos ldapuser.home_directory = homedir ldapuser.login_shell = shell ldapuser.username = username ldapuser.common_name = username if password is not None: ldapuser.set_password(password) _LOGGER.info('set password for LDAP user %s', ldapuser.dn) if ldapuser.username in ldapgroup.members: _LOGGER.info( 'LDAP user %s is already member of LDAP group %s', ldapuser.dn, ldapgroup.dn) else: ldapgroup.members.append(ldapuser.username) ldapgroup.save() _LOGGER.info( 'LDAP user %s has been added to LDAP group %s', ldapuser.dn, ldapgroup.dn) ldapuser.save() _LOGGER.info('LDAP user %s created', ldapuser.dn) return ldapuser.dn @shared_task(bind=True) def set_ldap_user_password(self, username, password): """ This task sets the password of an existing :py:class:`LDAP user `. :param str username: the user name :param str password: teh clear text password :return: :py:const:`True` if the password has been set, :py:const:`False` if the user does not exist. """ try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: _LOGGER.info('there is no LDAP user with username %s', username) return False ldapuser.set_password(password) ldapuser.save() _LOGGER.info("set new password for LDAP user %s", ldapuser.dn) return True @shared_task(bind=True) def add_ldap_user_to_group(self, username, groupname): """ This task adds the specified user to the given group. This task does nothing if the user is already member of the group. :param str username: the user name :param str groupname: the group name :raises celery.exceptions.Retry: if the user does not exist yet, :py:func:`create_ldap_user` should be called before :return: True if the user has been added to the group otherwise False :rtype: boolean """ try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) except LdapGroup.DoesNotExist: _LOGGER.error('LDAP group with groupname %s does not exist', groupname) except LdapUser.DoesNotExist as exc: _LOGGER.error('LDAP user with username %s does not exist', username) self.retry(exc=exc, time_limit=5) else: if ldapuser.username not in ldapgroup.members: ldapgroup.members.append(ldapuser.username) ldapgroup.save() _LOGGER.info( 'LDAP user %s has been added to LDAP group %s', ldapuser.username, ldapgroup.dn) else: _LOGGER.info( 'LDAP user %s is already in LDAP group %s', ldapuser.username, ldapgroup.dn) return True return False @shared_task def remove_ldap_user_from_group(username, groupname): """ This task removes the given user from the given group. :param str username: the user name :param str groupname: the group name :return: True if the user has been removed, False otherwise :rtype: boolean """ try: ldapgroup = LdapGroup.objects.get(name=groupname) ldapuser = LdapUser.objects.get(username=username) except LdapGroup.DoesNotExist: _LOGGER.error('LDAP group with groupname %s does not exist', groupname) except LdapUser.DoesNotExist: _LOGGER.error('LDAP user with username %s does not exist', username) else: if ldapuser.username in ldapgroup.members: ldapgroup.members.remove(ldapuser.username) _LOGGER.info( 'removed LDAP user %s from LDAP group %s', ldapuser.dn, ldapgroup.dn) ldapgroup.save() return True else: _LOGGER.info( 'LDAP user %s is not a member of LDAP group %s', ldapuser.dn, ldapgroup.dn) return False @shared_task def delete_ldap_user(username): """ This task deletes the given user. :param str username: the user name :return: True if the user has been deleted, False otherwise :rtype: boolean """ try: ldapuser = LdapUser.objects.get(username=username) except LdapUser.DoesNotExist: _LOGGER.info('there is no LDAP user with username %s', username) else: try: ldapgroup = LdapGroup.objects.get(gid=ldapuser.group) except LdapGroup.DoesNotExist: _LOGGER.info( 'LDAP group %s of LDAP user %s does not exist', ldapuser.group, ldapuser.dn) else: if ldapuser.username in ldapgroup.members: ldapgroup.members.remove(ldapuser.username) ldapgroup.save() _LOGGER.info( 'removed LDAP user %s from LDAP group %s', ldapuser.dn, ldapgroup.dn) userdn = ldapuser.dn ldapuser.delete() _LOGGER.info('deleted LDAP user %s', userdn) return True return False @shared_task def delete_ldap_group_if_empty(groupname): """ This task deletes the given group. :param str groupname: the group name :return: True if the user has been deleted, False otherwise :rtype: boolean """ try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: _LOGGER.info('LDAP group with groupname %s does not exist', groupname) else: if len(ldapgroup.members) == 0: groupdn = ldapgroup.dn ldapgroup.delete() _LOGGER.info( 'deleted LDAP group %s', groupdn) return True else: _LOGGER.info( 'LDAP group %s has not been deleted. It still has %d members', ldapgroup.dn, len(ldapgroup.members)) return False @shared_task def delete_ldap_group(groupname): """ This taks deletes the given group. :param str groupname: the group name :return: True if the user has been deleted, False otherwise :rtype: boolean """ try: ldapgroup = LdapGroup.objects.get(name=groupname) except LdapGroup.DoesNotExist: _LOGGER.info('LDAP group with name %s does not exist', groupname) else: groupdn = ldapgroup.dn ldapgroup.delete() _LOGGER.info('deleted LDAP group %s', groupdn) return True return False