From c8b76e975da257e3257f993ff6b711e2ce92c990 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Tue, 6 Sep 2022 16:35:51 +0200 Subject: [PATCH] Completing command line parameters in module pp_admintools.app.ldap and evaluating command line parameters in pp_admintools.app.remove_ldap_user. --- lib/pp_admintools/app/ldap.py | 144 ++++++++++++++++++++-- lib/pp_admintools/app/remove_ldap_user.py | 33 ++--- 2 files changed, 153 insertions(+), 24 deletions(-) diff --git a/lib/pp_admintools/app/ldap.py b/lib/pp_admintools/app/ldap.py index 98c7c0a..883ca41 100644 --- a/lib/pp_admintools/app/ldap.py +++ b/lib/pp_admintools/app/ldap.py @@ -18,8 +18,8 @@ except ImportError: from pathlib2 import Path # Third party modules +from fb_tools.common import pp from fb_tools.cfg_app import FbConfigApplication - from fb_tools.errors import FbAppError # Own modules @@ -36,7 +36,7 @@ from ..config.ldap import LdapConnectionInfo, LdapConfiguration # rom ..config.ldap import DEFAULT_PORT_LDAP, DEFAULT_PORT_LDAPS from ..config.ldap import DEFAULT_TIMEOUT, MAX_TIMEOUT -__version__ = '0.1.4' +__version__ = '0.2.1' LOG = logging.getLogger(__name__) _ = XLATOR.gettext @@ -146,6 +146,7 @@ class BaseLdapApplication(FbConfigApplication): """ use_default_ldap_connection = True + use_multiple_ldap_connections = False show_cmdline_ldap_timeout = True # ------------------------------------------------------------------------- @@ -156,6 +157,7 @@ class BaseLdapApplication(FbConfigApplication): config_dir=DEFAULT_CONFIG_DIR): self._password_file = None + self.ldap_instances = [] super(BaseLdapApplication, self).__init__( appname=appname, verbose=verbose, version=version, base_dir=base_dir, @@ -209,6 +211,7 @@ class BaseLdapApplication(FbConfigApplication): res['password_file'] = self.password_file res['show_cmdline_ldap_timeout'] = self.show_cmdline_ldap_timeout res['use_default_ldap_connection'] = self.use_default_ldap_connection + res['use_multiple_ldap_connections'] = self.use_multiple_ldap_connections return res @@ -220,8 +223,12 @@ class BaseLdapApplication(FbConfigApplication): super(BaseLdapApplication, self).init_arg_parser() - ldap_group = self.arg_parser.add_argument_group(_( - 'Options for the default LDAP connection')) + group_title = _('LDAP options') + if self.use_default_ldap_connection: + group_title = _('Options for the default LDAP connection') + elif self.use_multiple_ldap_connections: + group_title = _('Options fo LDAP connections') + ldap_group = self.arg_parser.add_argument_group(group_title) if self.use_default_ldap_connection: @@ -288,8 +295,36 @@ class BaseLdapApplication(FbConfigApplication): help=_("Use contents of PASSWORD_FILE as the password for simple authentication."), ) + else: + + arg_params = { + 'dest': "instance", + 'type': str, + 'metavar': _('INSTANCE'), + } + + help_single = _( + "The LDAP instance (LDAP cluster) from configuration, where to execute this " + "script. If not given, then the instance {!r} will be used.").format('default') + help_multi = _( + "The LDAP instance (LDAP cluster) from configuration, where to execute " + "this script. It is possible to give here the value {val_all!r}, " + "then all found LDAP instances except {default!r} are used. " + "It is alo possible to give the value {val_list!r}, then all configured " + "LDAP instances are shown, and the application is exiting. " + "If not given, then the instance {default!r} will be used.").format( + val_all='all', val_list='list', default='default') + + if self.use_multiple_ldap_connections: + arg_params['nargs'] = '*' + arg_params['help'] = help_multi + else: + arg_params['help'] = help_single + + ldap_group.add_argument('-I', '--instance', **arg_params) + if self.show_cmdline_ldap_timeout: - self.arg_parser.add_argument( + ldap_group.add_argument( '-T', '--timeout', metavar=_('SECONDS'), dest="ldap_timeout", action=TimeoutOptionAction, help=_( @@ -314,9 +349,102 @@ class BaseLdapApplication(FbConfigApplication): super(BaseLdapApplication, self).post_init() - if not self.use_default_ldap_connection: + v = getattr(self.args, 'ldap_timeout', None) + if v: + self.cfg.ldap_timeout = v + + self._init_default_connection() + + if self.use_default_ldap_connection: + self.ldap_instances = ['default'] + return + + LOG.debug(_("Checking given instances.")) + + insts = getattr(self.args, 'instance', None) + if self.verbose > 1: + LOG.debug(_("Given insts:") + ' ' + pp(insts)) + + if insts is None: + insts = [] + + if self.use_multiple_ldap_connections and len(insts) == 1 and insts[0].lower() == 'list': + self._show_ldap_instances() + self.exit(0) return + if len(insts): + for inst in insts: + inst_cleared = inst.strip().lower() + if inst_cleared != '': + self.ldap_instances.append(inst.lower()) + else: + self.ldap_instances = ['default'] + + self._verify_instances() + + # ------------------------------------------------------------------------- + def _show_ldap_instances(self): + + instances = [] + for inst in self.cfg.ldap_connection.keys(): + if inst != 'default': + instances.append(inst) + instances.sort(key=str.lower) + if 'default' in self.cfg.ldap_connection: + instances.insert(0, 'default') + + max_key_len = 1 + for inst in instances: + if len(inst) > max_key_len: + max_key_len = len(inst) + max_key_len += 1 + + title = _("Configured LDAP instances:") + print(title) + print('-' * len(title)) + print() + for inst in instances: + cfg = self.cfg.ldap_connection[inst] + print("{inst:<{width}} {url}/{base}".format( + inst=(inst + ':'), width=max_key_len, url=cfg.url, base=cfg.base_dn)) + print() + + # ------------------------------------------------------------------------- + def _verify_instances(self): + + if self.verbose > 1: + LOG.debug(_("Verifying given instances ...")) + + instances = [] + for inst in self.cfg.ldap_connection.keys(): + if inst != 'default': + instances.append(inst.lower()) + + if len(self.ldap_instances) == 1 and self.ldap_instances[0].lower() == 'all': + self.ldap_instances = instances + + else: + + if 'default' in self.cfg.ldap_connection: + instances.insert(0, 'default') + + all_ok = True + for given_inst in self.ldap_instances: + if given_inst not in instances: + LOG.error(_("LDAP instance {!r} not found in configuration.").format( + given_inst)) + all_ok = False + + if not all_ok: + self.exit(1) + + if self.verbose > 1: + LOG.debug(_("LDAP instances to use:") + ' ' + pp(self.ldap_instances)) + + # ------------------------------------------------------------------------- + def _init_default_connection(self): + if 'default' in self.cfg.ldap_connection: default_connection = self.cfg.ldap_connection['default'] else: @@ -353,10 +481,6 @@ class BaseLdapApplication(FbConfigApplication): if v: default_connection.bind_pw = v - v = getattr(self.args, 'ldap_timeout', None) - if v: - self.cfg.ldap_timeout = v - # ============================================================================= if __name__ == "__main__": diff --git a/lib/pp_admintools/app/remove_ldap_user.py b/lib/pp_admintools/app/remove_ldap_user.py index 7ea731d..3e0257a 100644 --- a/lib/pp_admintools/app/remove_ldap_user.py +++ b/lib/pp_admintools/app/remove_ldap_user.py @@ -20,7 +20,7 @@ from ..xlate import XLATOR from ..app.ldap import LdapAppError from ..app.ldap import BaseLdapApplication -__version__ = '0.2.0' +__version__ = '0.2.1' LOG = logging.getLogger(__name__) _ = XLATOR.gettext @@ -44,7 +44,10 @@ class RemoveLdapUserApplication(BaseLdapApplication): # ------------------------------------------------------------------------- def __init__(self, appname=None, base_dir=None): - self.ldap_instances = [] + self.use_default_ldap_connection = False + self.use_multiple_ldap_connections = True + self.show_cmdline_ldap_timeout = True + self.given_users = [] self.nologin_shell = self.default_nologin_shell self._deactivate = False @@ -115,18 +118,7 @@ class RemoveLdapUserApplication(BaseLdapApplication): ) remove_group.add_argument( - '-I', '--instance', dest="instance", nargs='*', type=str, - metavar=_('INSTANCE'), - help=_( - "The LDAP instance (LDAP cluster) from configuration, where to remove the user. " - "Multiple instances may be given. It is possible to give here the value " - "{val_all!r}, the then all found LDAP instances except {default!r} are used. " - "If not given, the the instance {default!r} will be used.").format( - val_all='all', default='default'), - ) - - remove_group.add_argument( - 'users', nargs='+', metavar=_('USER'), + 'users', nargs='*', metavar=_('USER'), help=_( "The user, which should be deactivated or removed. " "They may be given by their Uid (the alphanumeric POSIX name), " @@ -134,6 +126,19 @@ class RemoveLdapUserApplication(BaseLdapApplication): "different in the particular LDAP instances).") ) + # ------------------------------------------------------------------------- + def post_init(self): + """ + Method to execute 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.")) + self.exit(1) + # ============================================================================= if __name__ == "__main__": -- 2.39.5