From 610249c91cfe0f301ac68072bc015bfc8816f598 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Mon, 12 Jun 2023 14:31:19 +0200 Subject: [PATCH] Make the linter happy with lib/pp_admintools/app/remove_ldap_user.py --- lib/pp_admintools/app/remove_ldap_user.py | 186 +++++++++++----------- 1 file changed, 90 insertions(+), 96 deletions(-) diff --git a/lib/pp_admintools/app/remove_ldap_user.py b/lib/pp_admintools/app/remove_ldap_user.py index 152624d..91fc0d9 100644 --- a/lib/pp_admintools/app/remove_ldap_user.py +++ b/lib/pp_admintools/app/remove_ldap_user.py @@ -1,33 +1,32 @@ # -*- coding: utf-8 -*- """ +@summary: An application module for disabling or removing a user from LDAP. + @author: Frank Brehm @contact: frank.brehm@pixelpark.com @copyright: © 2023 by Frank Brehm, Berlin -@summary: An application module for disabling or removing a user from LDAP """ from __future__ import absolute_import # Standard modules +import crypt import logging import time -import crypt # Third party modules -from ldap3 import MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE - -# Own modules from fb_tools.collections import CIStringSet -from fb_tools.common import to_bool, is_sequence +from fb_tools.common import is_sequence, to_bool from fb_tools.xlate import format_list -from .. import pp - -from ..xlate import XLATOR +from ldap3 import MODIFY_ADD, MODIFY_DELETE, MODIFY_REPLACE -from .ldap import LdapAppError, FatalLDAPError +# Own modules from .ldap import BaseLdapApplication +from .ldap import FatalLDAPError, LdapAppError +from .. import pp +from ..xlate import XLATOR -__version__ = '0.6.0' +__version__ = '0.6.1' LOG = logging.getLogger(__name__) _ = XLATOR.gettext @@ -47,13 +46,13 @@ class RemoveLdapUserApplication(BaseLdapApplication): show_simulate_option = True - default_nologin_shell = "/usr/sbin/nologin" + default_nologin_shell = '/usr/sbin/nologin' value_inactive = 'inactive' raw_empty_passwd = 'none' # ------------------------------------------------------------------------- def __init__(self, appname=None, base_dir=None): - + """Initialize the RemoveLdapUserApplication object.""" self.use_default_ldap_connection = False self.use_multiple_ldap_connections = True self.show_cmdline_ldap_timeout = True @@ -72,11 +71,11 @@ class RemoveLdapUserApplication(BaseLdapApplication): self.shadow_expire = int(time.time() / 3600 / 24) - 100 desc = _( - "Disables or removes the given users from LDAP. " - "If disabling, then the user will not be really removed, but disabled " - "by locking the password, setting all status flags to {inact!r}, " - "assigning {shell!r} as login shell und removing the user from all groups. " - "When removing (or purging) the user will be really removed from LDAP.") + 'Disables or removes the given users from LDAP. ' + 'If disabling, then the user will not be really removed, but disabled ' + 'by locking the password, setting all status flags to {inact!r}, ' + 'assigning {shell!r} as login shell und removing the user from all groups. ' + 'When removing (or purging) the user will be really removed from LDAP.') desc = desc.format(inact=self.value_inactive, shell=self.nologin_shell) super(RemoveLdapUserApplication, self).__init__( @@ -87,7 +86,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------- @property def deactivate(self): - """Defines, that the given users will not be removed, bur deactivated instaed.""" + """Define, that the given users will not be removed, bur deactivated instaed.""" return self._deactivate @deactivate.setter @@ -109,7 +108,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def as_dict(self, short=True): """ - Transforms the elements of the object into a dict + Transform the elements of the object into a dict. @param short: don't include local properties in resulting dict. @type short: bool @@ -117,7 +116,6 @@ class RemoveLdapUserApplication(BaseLdapApplication): @return: structure as dict @rtype: dict """ - res = super(RemoveLdapUserApplication, self).as_dict(short=short) res['deactivate'] = self.deactivate @@ -127,30 +125,30 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def init_arg_parser(self): - + """Initialize specific command line parameters for this application.""" remove_group = self.arg_parser.add_argument_group(_('Removing options')) remove_mode_group = remove_group.add_mutually_exclusive_group() - help_default = ' ' + _("This is the default.") - help_mutual = " " + _("This is mutually exclusive to {!r}.") + help_default = ' ' + _('This is the default.') + help_mutual = ' ' + _('This is mutually exclusive to {!r}.') - help_txt = _("Deactivating the user instead of removing it.") + help_txt = _('Deactivating the user instead of removing it.') help_txt += help_mutual.format('--remove') if self.deactivate: help_txt += help_default remove_mode_group.add_argument( - '-d', '--deactivate', dest="deactivate", action='store_true', help=help_txt) + '-d', '--deactivate', dest='deactivate', action='store_true', help=help_txt) - help_txt = _("Removing the user from LDAP.") + help_txt = _('Removing the user from LDAP.') help_txt += help_mutual.format('--deactivate') if not self.deactivate: help_txt += help_default remove_mode_group.add_argument( - '-R', '--remove', dest="remove", action='store_true', help=help_txt) + '-R', '--remove', dest='remove', action='store_true', help=help_txt) help_txt = _( "Don't remove all mail addresses of the users to remove from all " - "mailing lists.") + 'mailing lists.') remove_group.add_argument( '-N', '--no-del-mail-addresses-from-lists', dest='no_del_mails', action='store_true', help=help_txt) @@ -158,10 +156,10 @@ class RemoveLdapUserApplication(BaseLdapApplication): remove_group.add_argument( 'users', nargs='*', metavar=_('USER'), help=_( - "The user, which should be deactivated or removed. " - "They may be given by their Uid (the alphanumeric POSIX name), " - "their mail address or their LDAP DN (be aware, that this may be " - "different in the particular LDAP instances).") + 'The user, which should be deactivated or removed. ' + 'They may be given by their Uid (the alphanumeric POSIX name), ' + 'their mail address or their LDAP DN (be aware, that this may be ' + 'different in the particular LDAP instances).') ) super(RemoveLdapUserApplication, self).init_arg_parser() @@ -173,15 +171,12 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def post_init(self): - """ - Method to execute before calling run(). - """ - + """Execute isome steps before calling run().""" super(RemoveLdapUserApplication, self).post_init() given_users = getattr(self.args, 'users', []) if not given_users: - LOG.error(_("No users to remove given.")) + LOG.error(_('No users to remove given.')) self.exit(1) # deactivate = bool(getattr(self.args, 'remove', False)) @@ -198,16 +193,15 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def check_instances(self): - """Checking given instances for admin and read/write access.""" - - msg = _("Checking given instances for admin and read/write access.") + """Check given instances for admin and read/write access.""" + msg = _('Checking given instances for admin and read/write access.') LOG.debug(msg) all_ok = True for inst_name in self.ldap_instances: if inst_name not in self.cfg.ldap_connection: - msg = _("LDAP instance {!r} not found in configuration.").format(inst_name) + msg = _('LDAP instance {!r} not found in configuration.').format(inst_name) LOG.error(msg) all_ok = False continue @@ -215,12 +209,12 @@ class RemoveLdapUserApplication(BaseLdapApplication): inst = self.cfg.ldap_connection[inst_name] if inst.readonly: - msg = _("LDAP instance {!r} has only readonly access.").format(inst_name) + msg = _('LDAP instance {!r} has only readonly access.').format(inst_name) LOG.error(msg) all_ok = False if not inst.is_admin: - msg = _("No admin access to LDAP instance {!r}.").format(inst_name) + msg = _('No admin access to LDAP instance {!r}.').format(inst_name) LOG.error(msg) all_ok = False @@ -237,12 +231,12 @@ class RemoveLdapUserApplication(BaseLdapApplication): self.exit(5) if not self.dns: - msg = _("All given users were not found in any LDAP instance.") + msg = _('All given users were not found in any LDAP instance.') LOG.warn(msg) self.exit(1) if self.verbose > 1: - msg = _("Evaluated DNs to remove:") + msg = _('Evaluated DNs to remove:') LOG.debug(msg + '\n' + pp(self.dns)) if not self.request_for_remove(): @@ -251,15 +245,15 @@ class RemoveLdapUserApplication(BaseLdapApplication): if not self.quiet: print() if self.deactivate: - msg = _("Start disabling user entries in:") + msg = _('Start disabling user entries in:') else: - msg = _("Start removing user entries in:") + msg = _('Start removing user entries in:') self.countdown(number=3, delay=1, prompt=msg) else: if self.deactivate: - msg = _("Start disabling user entries ...") + msg = _('Start disabling user entries ...') else: - msg = _("Start removing user entries ...") + msg = _('Start removing user entries ...') LOG.warn(msg) for inst in self.dns: @@ -268,15 +262,15 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def request_for_remove(self): - + """Ask the operator for really removing the given user(s).""" if self.quiet: return True print() if self.deactivate: - msg = _("Do you really want to deactivate the following users?") + msg = _('Do you really want to deactivate the following users?') else: - msg = _("Do you really want to remove the following users?") + msg = _('Do you really want to remove the following users?') print(self.colored(msg, 'CYAN')) print(self.colored(('-' * len(msg)), 'CYAN')) print() @@ -294,7 +288,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): for dn in self.dns[inst]: if not first: uri = ' ' - msg = " {a} {uri:<{max_len}} - {dn}".format( + msg = ' {a} {uri:<{max_len}} - {dn}'.format( a=self.colored('*', 'CYAN'), uri=uri, max_len=max_len, dn=self.colored(dn, 'CYAN')) print(msg) @@ -302,21 +296,21 @@ class RemoveLdapUserApplication(BaseLdapApplication): print() if self.deactivate: - msg = _("Deactivate [{yes}/{no}]?") + msg = _('Deactivate [{yes}/{no}]?') else: - msg = _("Remove [{yes}/{no}]?") + msg = _('Remove [{yes}/{no}]?') msg = msg.format( yes=self.colored(_('yes'), 'RED'), no=self.colored(_('No'), 'GREEN')) + ' ' return self.ask_for_yes_or_no(msg) # ------------------------------------------------------------------------- def eval_user_dns(self, user): - - LOG.debug(_("Evaluating DNs of the user {!r} to remove ...").format(user)) + """Try to evaluate the DNs of the users to remove by their UID, DN or mail address.""" + LOG.debug(_('Evaluating DNs of the user {!r} to remove ...').format(user)) usr = user.strip() if usr == '': - msg = _("Empty user given.") + msg = _('Empty user given.') LOG.warn(msg) self.wrong_users = True return @@ -326,14 +320,14 @@ class RemoveLdapUserApplication(BaseLdapApplication): dns = self.get_user_dn(usr, inst) if dns: if self.verbose > 2: - msg = _("Got DN {dn!r} for user {user!r} in LDAP instance {inst}.").format( + msg = _('Got DN {dn!r} for user {user!r} in LDAP instance {inst}.').format( dn=dns, user=usr, inst=connect_info.url) LOG.debug(msg) if inst not in self.dns: self.dns[inst] = [] if is_sequence(dns): if len(dns) > 1: - msg = _("Found {nr} entries for user {u!r} in LDAP instance {i}.").format( + msg = _('Found {nr} entries for user {u!r} in LDAP instance {i}.').format( nr=len(dns), u=usr, i=connect_info.url) LOG.warn(msg) self.wrong_users = True @@ -345,18 +339,18 @@ class RemoveLdapUserApplication(BaseLdapApplication): if dns not in self.dns[inst]: self.dns[inst].append(dns) else: - msg = _("Did not found user {user!r} in LDAP instance {inst}.").format( + msg = _('Did not found user {user!r} in LDAP instance {inst}.').format( user=usr, inst=connect_info.url) LOG.info(msg) # ------------------------------------------------------------------------- def remove_users_from_inst(self, inst): - + """Remove finally all given users from LDAP.""" connect_info = self.cfg.ldap_connection[inst] if self.deactivate: - msg = _("Deactivating all given users from {} ...").format(connect_info.url) + msg = _('Deactivating all given users from {} ...').format(connect_info.url) else: - msg = _("Removing all given users from {} ...").format(connect_info.url) + msg = _('Removing all given users from {} ...').format(connect_info.url) LOG.info(msg) for dn in self.dns[inst]: @@ -367,20 +361,20 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def remove_user(self, inst, dn): - + """Remove the given user from LDAP or deactivate it.""" connect_info = self.cfg.ldap_connection[inst] if self.deactivate: - msg = _("Deactivating user {dn!r} from {inst} ...").format( + msg = _('Deactivating user {dn!r} from {inst} ...').format( dn=dn, inst=connect_info.url) else: - msg = _("Removing user {dn!r} from {inst} ...").format(dn=dn, inst=connect_info.url) + msg = _('Removing user {dn!r} from {inst} ...').format(dn=dn, inst=connect_info.url) LOG.info(msg) entry = self.get_entry(dn, inst) attributes = self.normalized_attributes(entry) if self.verbose > 1: - msg = _("Attributes of {!r}:").format(dn) + msg = _('Attributes of {!r}:').format(dn) LOG.debug(msg + '\n' + pp(attributes.as_dict())) if not self.setting_user_status(inst, dn, attributes): @@ -404,16 +398,16 @@ class RemoveLdapUserApplication(BaseLdapApplication): try: self.delete_entry(inst, dn) except FatalLDAPError as e: - msg = _("{c} on removing user {dn!r}: {e}").format( + msg = _('{c} on removing user {dn!r}: {e}').format( c=e.__class__.__name__, dn=dn, e=e) LOG.error(msg) return False if self.deactivate: - msg = _("User {dn!r} successful deactivated on {inst}.").format( + msg = _('User {dn!r} successful deactivated on {inst}.').format( dn=dn, inst=connect_info.url) else: - msg = _("User {dn!r} successful removed from {inst}.").format( + msg = _('User {dn!r} successful removed from {inst}.').format( dn=dn, inst=connect_info.url) LOG.info(msg) @@ -421,7 +415,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def setting_user_status(self, inst, dn, attributes): - + """Set the user status of the given user in LDAP.""" connect_info = self.cfg.ldap_connection[inst] changes = {} @@ -439,12 +433,12 @@ class RemoveLdapUserApplication(BaseLdapApplication): if 'posixAccount' in attributes['objectClass']: changes['loginShell'] = [(MODIFY_REPLACE, self.nologin_shell)] - LOG.info(_("Updating user info for {dn!r} on {inst} ...").format( + LOG.info(_('Updating user info for {dn!r} on {inst} ...').format( dn=dn, inst=connect_info.url)) try: self.modify_entry(inst, dn, changes) except FatalLDAPError as e: - msg = _("{c} on deactivating user {dn!r}: {e}").format( + msg = _('{c} on deactivating user {dn!r}: {e}').format( c=e.__class__.__name__, dn=dn, e=e) msg += '\n' + _('Changes:') + '\n' + pp(changes) LOG.error(msg) @@ -454,24 +448,24 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def remove_all_memberships(self, inst, dn): - + """Remove the given DN from all LDAP groups as a member.""" connect_info = self.cfg.ldap_connection[inst] group_dns = self.get_group_memberships(inst, dn) if not group_dns: - msg = _("Did not found any group memberships of {dn!r} in {inst}.").format( + msg = _('Did not found any group memberships of {dn!r} in {inst}.').format( dn=dn, inst=connect_info.url) LOG.debug(msg) return True for group_dn in group_dns: - LOG.info(_("Removing user {u!r} from group {g!r} ...").format(u=dn, g=group_dn)) + LOG.info(_('Removing user {u!r} from group {g!r} ...').format(u=dn, g=group_dn)) changes = {'member': [(MODIFY_DELETE, dn)], } try: self.modify_entry(inst, group_dn, changes) except FatalLDAPError as e: - msg = _("{c} on removing user {dn!r} from group {g!r}: {e}").format( + msg = _('{c} on removing user {dn!r} from group {g!r}: {e}').format( c=e.__class__.__name__, dn=dn, g=group_dn, e=e) msg += '\n' + _('Changes:') + '\n' + pp(changes) LOG.error(msg) @@ -481,24 +475,24 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def remove_all_unique_memberships(self, inst, dn): - + """Remove the given DN from all LDAP groups as a uniqueMember.""" connect_info = self.cfg.ldap_connection[inst] group_dns = self.get_unique_group_memberships(inst, dn) if not group_dns: - msg = _("Did not found any unique group memberships of {dn!r} in {inst}.").format( + msg = _('Did not found any unique group memberships of {dn!r} in {inst}.').format( dn=dn, inst=connect_info.url) LOG.debug(msg) return True for group_dn in group_dns: - LOG.info(_("Removing user {u!r} from group {g!r} ...").format(u=dn, g=group_dn)) + LOG.info(_('Removing user {u!r} from group {g!r} ...').format(u=dn, g=group_dn)) changes = {'uniqueMember': [(MODIFY_DELETE, dn)], } try: self.modify_entry(inst, group_dn, changes) except FatalLDAPError as e: - msg = _("{c} on removing user {dn!r} from group {g!r}: {e}").format( + msg = _('{c} on removing user {dn!r} from group {g!r}: {e}').format( c=e.__class__.__name__, dn=dn, g=group_dn, e=e) msg += '\n' + _('Changes:') + '\n' + pp(changes) LOG.error(msg) @@ -508,28 +502,28 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def remove_all_posixgroup_memberships(self, inst, uid): - + """Remove the given UID from all legacy POSIX groups.""" connect_info = self.cfg.ldap_connection[inst] - msg = _("Deleting user {uid!r} from all POSIX groups in {inst}.").format( + msg = _('Deleting user {uid!r} from all POSIX groups in {inst}.').format( uid=uid, inst=connect_info.url) LOG.debug(msg) group_dns = self.get_posix_group_memberships(inst, uid) if not group_dns: - msg = _("Did not found any POSIX group memberships of {uid!r} in {inst}.").format( + msg = _('Did not found any POSIX group memberships of {uid!r} in {inst}.').format( uid=uid, inst=connect_info.url) LOG.debug(msg) return True for group_dn in group_dns: - LOG.info(_("Removing user {u!r} from group {g!r} ...").format(u=uid, g=group_dn)) + LOG.info(_('Removing user {u!r} from group {g!r} ...').format(u=uid, g=group_dn)) changes = {'memberUid': [(MODIFY_DELETE, uid)], } try: self.modify_entry(inst, group_dn, changes) except FatalLDAPError as e: - msg = _("{c} on removing user {dn!r} from group {g!r}: {e}").format( + msg = _('{c} on removing user {dn!r} from group {g!r}: {e}').format( c=e.__class__.__name__, dn=uid, g=group_dn, e=e) msg += '\n' + _('Changes:') + '\n' + pp(changes) LOG.error(msg) @@ -539,28 +533,28 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def remove_all_sudogroup_memberships(self, inst, uid): - + """Remove the given UID from all sudo-Roles.""" connect_info = self.cfg.ldap_connection[inst] - msg = _("Deleting user {uid!r} from all sudo groups in {inst}.").format( + msg = _('Deleting user {uid!r} from all sudo groups in {inst}.').format( uid=uid, inst=connect_info.url) LOG.debug(msg) group_dns = self.get_sudo_group_memberships(inst, uid) if not group_dns: - msg = _("Did not found any sudo group memberships of {uid!r} in {inst}.").format( + msg = _('Did not found any sudo group memberships of {uid!r} in {inst}.').format( uid=uid, inst=connect_info.url) LOG.debug(msg) return True for group_dn in group_dns: - LOG.info(_("Removing user {u!r} from group {g!r} ...").format(u=uid, g=group_dn)) + LOG.info(_('Removing user {u!r} from group {g!r} ...').format(u=uid, g=group_dn)) changes = {'sudoUser': [(MODIFY_DELETE, uid)], } try: self.modify_entry(inst, group_dn, changes) except FatalLDAPError as e: - msg = _("{c} on removing user {dn!r} from group {g!r}: {e}").format( + msg = _('{c} on removing user {dn!r} from group {g!r}: {e}').format( c=e.__class__.__name__, dn=uid, g=group_dn, e=e) msg += '\n' + _('Changes:') + '\n' + pp(changes) LOG.error(msg) @@ -571,7 +565,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def del_mails_from_lists(self, inst, dn, attributes): """Remove mail addresses of users from all mailing lists.""" - connect_info = self.cfg.ldap_connection[inst] + connect_info = self.cfg.ldap_connection[inst] # noqa mail_addresses = CIStringSet() for attr in attributes.keys(): @@ -584,7 +578,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): mail_addresses.add(values) if not len(mail_addresses): - msg = _("No mail addresses found to remove for user {!r}.").format(dn) + msg = _('No mail addresses found to remove for user {!r}.').format(dn) LOG.debug(msg) return @@ -594,7 +588,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ============================================================================= -if __name__ == "__main__": +if __name__ == '__main__': pass -- 2.39.5