class servicedelegationrule_find(LDAPSearch): __doc__ = _('Search for service delegations rule.') has_output_params = LDAPSearch.has_output_params + output_params msg_summary = ngettext('%(count)d service delegation rule matched', '%(count)d service delegation rules matched', 0)
class service_find(LDAPSearch): __doc__ = _('Search for IPA services.') msg_summary = ngettext('%(count)d service matched', '%(count)d services matched', 0) member_attributes = ['managedby'] takes_options = LDAPSearch.takes_options has_output_params = LDAPSearch.has_output_params + output_params def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): assert isinstance(base_dn, DN) # lisp style! custom_filter = '(&(objectclass=ipaService)' \ '(!(objectClass=posixAccount))' \ '(!(|(krbprincipalname=kadmin/*)' \ '(krbprincipalname=K/M@*)' \ '(krbprincipalname=krbtgt/*))' \ ')' \ ')' return (ldap.combine_filters((custom_filter, filter), rules=ldap.MATCH_ALL), base_dn, scope) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated for entry in entries: (dn, entry_attrs) = entry self.obj.get_password_attributes(ldap, dn, entry_attrs) set_certificate_attrs(entry_attrs) return truncated
class plugins(LocalOrRemote): __doc__ = _('Show all loaded plugins.') msg_summary = ngettext('%(count)d plugin loaded', '%(count)d plugins loaded', 0) takes_options = LocalOrRemote.takes_options + (Flag( 'all', cli_name='all', doc=_('retrieve and print all attributes from the server. ' 'Affects command output.'), exclude='webui', flags=['no_option', 'no_output'], default=True, ), ) has_output = ( Output('result', dict, 'Dictionary mapping plugin names to bases'), Output( 'count', type=int, doc=_('Number of plugins loaded'), ), summary, ) def execute(self, **options): result = {} for namespace in self.api: for plugin in self.api[namespace](): cls = type(plugin) key = '{}.{}'.format(cls.__module__, cls.__name__) result.setdefault(key, []).append(namespace) return dict(result=result, )
class selinuxusermap_find(LDAPSearch): __doc__ = _('Search for SELinux User Maps.') msg_summary = ngettext('%(count)d SELinux User Map matched', '%(count)d SELinux User Maps matched', 0) def execute(self, *args, **options): # If searching on hbacrule we need to find the uuid to search on if options.get('seealso'): hbacrule = options['seealso'] # If a complete DN is passed we can skip calling hbacrule-show try: tmpdn = DN(hbacrule) except ValueError: tmpdn = DN() if DN(api.env.container_hbac, api.env.basedn) not in tmpdn: try: hbac = api.Command['hbacrule_show'](hbacrule, all=True)['result'] dn = hbac['dn'] except errors.NotFound: return dict(count=0, result=[], truncated=False) else: dn = tmpdn options['seealso'] = dn return super(selinuxusermap_find, self).execute(*args, **options) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated for attrs in entries: self.obj._convert_seealso(ldap, attrs, **options) return truncated
class servicedelegationtarget_find(LDAPSearch): __doc__ = _('Search for service delegation target.') msg_summary = ngettext('%(count)d service delegation target matched', '%(count)d service delegation targets matched', 0) def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, term=None, **options): """ Exclude rules from the search output. A target contains a subset of a rule objectclass. """ search_kw = self.args_options_2_entry(**options) search_kw['objectclass'] = self.obj.object_class attr_filter = ldap.make_filter(search_kw, rules=ldap.MATCH_ALL) rule_kw = {'objectclass': 'ipakrb5delegationacl'} target_filter = ldap.make_filter(rule_kw, rules=ldap.MATCH_NONE) attr_filter = ldap.combine_filters((target_filter, attr_filter), rules=ldap.MATCH_ALL) search_kw = {} for a in self.obj.default_attributes: search_kw[a] = term term_filter = ldap.make_filter(search_kw, exact=False) sfilter = ldap.combine_filters((term_filter, attr_filter), rules=ldap.MATCH_ALL) return sfilter, base_dn, ldap.SCOPE_ONELEVEL
class sudocmdgroup_find(LDAPSearch): __doc__ = _('Search for Sudo Command Groups.') msg_summary = ngettext( '%(count)d Sudo Command Group matched', '%(count)d Sudo Command Groups matched', 0 )
class otptoken_find(LDAPSearch): __doc__ = _('Search for OTP token.') msg_summary = ngettext('%(count)d OTP token matched', '%(count)d OTP tokens matched', 0) def pre_callback(self, ldap, filters, attrs_list, *args, **kwargs): # This is a hack, but there is no other way to # replace the objectClass when searching type = kwargs.get('type', '') if type not in TOKEN_TYPES: type = '' filters = filters.replace("(objectclass=ipatoken)", "(objectclass=ipatoken%s)" % type) attrs_list.append("objectclass") return super(otptoken_find, self).pre_callback(ldap, filters, attrs_list, *args, **kwargs) def args_options_2_entry(self, *args, **options): entry = super(otptoken_find, self).args_options_2_entry(*args, **options) _normalize_owner(self.api.Object.user, entry) return entry def post_callback(self, ldap, entries, truncated, *args, **options): for entry in entries: _set_token_type(entry, **options) _convert_owner(self.api.Object.user, entry, options) return super(otptoken_find, self).post_callback(ldap, entries, truncated, *args, **options)
class plugins(LocalOrRemote): __doc__ = _('Show all loaded plugins.') msg_summary = ngettext('%(count)d plugin loaded', '%(count)d plugins loaded', 0) takes_options = LocalOrRemote.takes_options + (Flag( 'all', cli_name='all', doc= _('retrieve and print all attributes from the server. Affects command output.' ), exclude='webui', flags=['no_output'], default=True, ), ) has_output = ( Output('result', dict, 'Dictionary mapping plugin names to bases'), Output( 'count', type=int, doc=_('Number of plugins loaded'), ), summary, ) def execute(self, **options): plugins = sorted(self.api.plugins, key=lambda o: o.plugin) return dict( result=dict((p.plugin, p.bases) for p in plugins), count=len(plugins), )
class ca_find(LDAPSearch): __doc__ = _("Search for CAs.") msg_summary = ngettext('%(count)d CA matched', '%(count)d CAs matched', 0) def execute(self, *keys, **options): ca_enabled_check() return super(ca_find, self).execute(*keys, **options)
class automountmap_find(LDAPSearch): __doc__ = _('Search for an automount map.') msg_summary = ngettext( '%(count)d automount map matched', '%(count)d automount maps matched', 0 )
class automountlocation_find(LDAPSearch): __doc__ = _('Search for an automount location.') msg_summary = ngettext( '%(count)d automount location matched', '%(count)d automount locations matched', 0 )
class selinuxusermap_find(LDAPSearch): __doc__ = _('Search for SELinux User Maps.') msg_summary = ngettext('%(count)d SELinux User Map matched', '%(count)d SELinux User Maps matched', 0) def execute(self, *args, **options): # If searching on hbacrule we need to find the uuid to search on if options.get('seealso'): hbacrule = options['seealso'] try: hbac = api.Command['hbacrule_show'](hbacrule, all=True)['result'] dn = hbac['dn'] except errors.NotFound: return dict(count=0, result=[], truncated=False) options['seealso'] = dn return super(selinuxusermap_find, self).execute(*args, **options) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated for attrs in entries: self.obj._convert_seealso(ldap, attrs, **options) return truncated
class stageuser_find(baseuser_find): __doc__ = _('Search for stage users.') member_attributes = ['memberof'] has_output_params = baseuser_find.has_output_params + stageuser_output_params def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options): assert isinstance(base_dn, DN) self.pre_common_callback(ldap, filter, attrs_list, base_dn, scope, *keys, **options) container_filter = ldap.make_filter_from_attr('objectclass', 'posixaccount') # provisioning system can create non posixaccount stage user # but then they have to create inetOrgPerson stage user stagefilter = filter.replace( container_filter, "(|%s(objectclass=inetOrgPerson))" % container_filter) logger.debug("stageuser_find: pre_callback new filter=%s ", stagefilter) return (stagefilter, base_dn, scope) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated self.post_common_callback(ldap, entries, lockout=True, **options) return truncated msg_summary = ngettext('%(count)d user matched', '%(count)d users matched', 0)
def interactive_prompt_callback(self, kw): try: has_cli_options(self, kw, self.no_option_msg, True) except errors.OptionError: pass else: # some record type entered, skip this helper return # get DNS record first so that the NotFound exception is raised # before the helper would start dns_record = self.api.Command['dnsrecord_show']( kw['dnszoneidnsname'], kw['idnsname'])['result'] self.Backend.textui.print_plain( _("No option to modify specific record provided.")) # ask user for records to be removed self.Backend.textui.print_plain(_(u'Current DNS record contents:\n')) record_params = [] for attr in dns_record: try: param = self.params[attr] except KeyError: continue rrtype = get_record_rrtype(param.name) if not rrtype: continue record_params.append((param, rrtype)) rec_type_content = u', '.join(dns_record[param.name]) self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content)) self.Backend.textui.print_plain(u'') # ask what records to remove for param, rrtype in record_params: rec_values = list(dns_record[param.name]) for rec_value in dns_record[param.name]: rec_values.remove(rec_value) mod_value = self.Backend.textui.prompt_yesno( _("Modify %(name)s '%(value)s'?") % dict(name=param.label, value=rec_value), default=False) if mod_value is True: user_options = prompt_parts(rrtype, self, mod_dnsvalue=rec_value) kw[param.name] = [rec_value] kw.update(user_options) if rec_values: self.Backend.textui.print_plain( ngettext( u'%(count)d %(type)s record skipped. Only one value per DNS record type can be modified at one time.', u'%(count)d %(type)s records skipped. Only one value per DNS record type can be modified at one time.', 0) % dict(count=len(rec_values), type=rrtype)) break
class pkinit_status(Search): __doc__ = _('Report PKINIT status on the IPA masters') msg_summary = ngettext('%(count)s server matched', '%(count)s servers matched', 0) takes_options = Search.takes_options + ( Int( 'timelimit?', label=_('Time Limit'), doc=_('Time limit of search in seconds (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), Int( 'sizelimit?', label=_('Size Limit'), doc=_('Maximum number of entries returned (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), ) def get_pkinit_status(self, server, status): backend = self.api.Backend.serverroles ipa_master_config = backend.config_retrieve("IPA master") if server is not None: servers = [server] else: servers = ipa_master_config['ipa_master_server'] pkinit_servers = ipa_master_config['pkinit_server_server'] for s in servers: pkinit_status = { u'server_server': s, u'status': (u'enabled' if s in pkinit_servers else u'disabled') } if status is not None and pkinit_status[u'status'] != status: continue yield pkinit_status def execute(self, *keys, **options): if keys: return dict(result=[], count=0, truncated=False) server = options.get('server_server', None) status = options.get('status', None) if server is not None: self.api.Object.server_role.ensure_master_exists(server) result = sorted(self.get_pkinit_status(server, status)) return dict(result=result, count=len(result), truncated=False)
class certprofile_find(LDAPSearch): __doc__ = _("Search for Certificate Profiles.") msg_summary = ngettext('%(count)d profile matched', '%(count)d profiles matched', 0) def execute(self, *args, **kwargs): ca_enabled_check(self.api) return super(certprofile_find, self).execute(*args, **kwargs)
class service_find(LDAPSearch): __doc__ = _('Search for IPA services.') msg_summary = ngettext('%(count)d service matched', '%(count)d services matched', 0) member_attributes = ['managedby'] sort_result_entries = False takes_options = LDAPSearch.takes_options has_output_params = LDAPSearch.has_output_params + output_params def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): assert isinstance(base_dn, DN) # lisp style! custom_filter = '(&(objectclass=ipaService)' \ '(!(objectClass=posixAccount))' \ '(!(|(krbprincipalname=kadmin/*)' \ '(krbprincipalname=K/M@*)' \ '(krbprincipalname=krbtgt/*))' \ ')' \ ')' if options.get('pkey_only', False): attrs_list.append('krbprincipalname') return (ldap.combine_filters((custom_filter, filter), rules=ldap.MATCH_ALL), base_dn, scope) def post_callback(self, ldap, entries, truncated, *args, **options): # we have to sort entries manually instead of relying on inherited # mechanisms def sort_key(x): if 'krbcanonicalname' in x: return x['krbcanonicalname'][0] else: return x['krbprincipalname'][0] entries.sort(key=sort_key) if options.get('pkey_only', False): return truncated for entry_attrs in entries: self.obj.get_password_attributes(ldap, entry_attrs.dn, entry_attrs) principal = entry_attrs['krbprincipalname'] if isinstance(principal, (tuple, list)): principal = principal[0] try: set_certificate_attrs(entry_attrs) except errors.CertificateFormatError as e: self.add_message( messages.CertificateInvalid(subject=principal, reason=e)) self.log.error("Invalid certificate: {err}".format(err=e)) del (entry_attrs['usercertificate']) set_kerberos_attrs(entry_attrs, options) rename_ipaallowedtoperform_from_ldap(entry_attrs, options) self.obj.populate_krbcanonicalname(entry_attrs, options) return truncated
class server_role_find(Search): __doc__ = _('Find a server role on a server(s)') obj_name = 'server_role' attr_name = 'find' msg_summary = ngettext('%(count)s server role matched', '%(count)s server roles matched', 0) takes_options = Search.takes_options + ( Int( 'timelimit?', label=_('Time Limit'), doc=_('Time limit of search in seconds (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), Int( 'sizelimit?', label=_('Size Limit'), doc=_('Maximum number of entries returned (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), Flag( 'include_master', doc=_('Include IPA master entries'), )) def execute(self, *keys, **options): if keys: return dict(result=[], count=0, truncated=False) server = options.get('server_server', None) role_name = options.get('role_servrole', None) status = options.get('status', None) if server is not None: self.obj.ensure_master_exists(server) role_status = self.obj.backend.server_role_search( server_server=server, role_servrole=role_name, status=status) # Don't display "IPA master" information unless the role is # requested explicitly. All servers are considered IPA masters, # except for replicas during installation. if options.get('include_master') or role_name == "IPA master": result = role_status else: result = [ r for r in role_status if r[u'role_servrole'] != "IPA master" ] return dict( result=result, count=len(result), truncated=False, )
class baseidoverride_find(LDAPSearch): __doc__ = _('Search for an ID override.') msg_summary = ngettext('%(count)d ID override matched', '%(count)d ID overrides matched', 0) def post_callback(self, ldap, entries, truncated, *args, **options): for entry in entries: self.obj.convert_anchor_to_human_readable_form(entry, **options) return truncated
class certmap_match(Search): __doc__ = _(""" Search for users matching the provided certificate. This command relies on SSSD to retrieve the list of matching users and may return cached data. For more information on purging SSSD cache, please refer to sss_cache documentation. """) msg_summary = ngettext('%(count)s user matched', '%(count)s users matched', 0) def get_summary_default(self, output): """ Need to sum the numbre of matching users for each domain. """ count = sum(len(entry['uid']) for entry in output['result']) return self.msg_summary % dict(count=count) def get_args(self): for arg in super(certmap_match, self).get_args(): if arg.name == 'criteria': continue yield arg yield Bytes('certificate', validate_certificate, cli_name='certificate', label=_('Certificate'), doc=_('Base-64 encoded user certificate'), flags=['virtual_attribute']) def execute(self, *args, **options): """ Search for users matching the provided certificate. The search is performed using SSSD's DBus interface Users.ListByCertificate. SSSD does the lookup based on certificate mapping rules, using FreeIPA domain and trusted domains. :raise RemoteRetrieveError: if DBus returns an exception """ sssd = _sssd() cert = args[0] users = sssd.list_users_by_cert(cert) result = [{ 'domain': domain, 'uid': userlist } for (domain, userlist) in users.items()] count = len(result) return dict( result=result, count=count, truncated=False, )
class user_find(baseuser_find): __doc__ = _('Search for users.') member_attributes = ['memberof'] has_output_params = baseuser_find.has_output_params + user_output_params msg_summary = ngettext('%(count)d user matched', '%(count)d users matched', 0) takes_options = LDAPSearch.takes_options + (Flag( 'whoami', label=_('Self'), doc=_('Display user record for current Kerberos principal'), ), ) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options): assert isinstance(base_dn, DN) self.pre_common_callback(ldap, filter, attrs_list, base_dn, scope, *keys, **options) if options.get('whoami'): return ("(&(objectclass=posixaccount)(krbprincipalname=%s))"%\ getattr(context, 'principal'), base_dn, scope) preserved = options.get('preserved', False) if preserved is None: base_dn = self.api.env.basedn scope = ldap.SCOPE_SUBTREE elif preserved: base_dn = DN(self.obj.delete_container_dn, self.api.env.basedn) else: base_dn = DN(self.obj.active_container_dn, self.api.env.basedn) return (filter, base_dn, scope) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated if options.get('preserved', False) is None: base_dns = ( DN(self.obj.active_container_dn, self.api.env.basedn), DN(self.obj.delete_container_dn, self.api.env.basedn), ) entries[:] = [ e for e in entries if any( e.dn.endswith(bd) for bd in base_dns) ] self.post_common_callback(ldap, entries, lockout=False, **options) for entry in entries: self.obj.get_preserved_attribute(entry, options) return truncated
class radiusproxy_find(LDAPSearch): __doc__ = _('Search for RADIUS proxy servers.') msg_summary = ngettext('%(count)d RADIUS proxy server matched', '%(count)d RADIUS proxy servers matched', 0) def get_options(self): for option in super(radiusproxy_find, self).get_options(): if option.name == 'ipatokenradiussecret': option = option.clone(flags={'no_option'}) yield option
class server_role_find(Search): __doc__ = _('Find a server role on a server(s)') obj_name = 'server_role' attr_name = 'find' msg_summary = ngettext('%(count)s server role matched', '%(count)s server roles matched', 0) takes_options = Search.takes_options + ( Int( 'timelimit?', label=_('Time Limit'), doc=_('Time limit of search in seconds (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), Int( 'sizelimit?', label=_('Size Limit'), doc=_('Maximum number of entries returned (0 is unlimited)'), flags=['no_display'], minvalue=0, autofill=False, ), ) def execute(self, *keys, **options): if keys: return dict( result=[], count=0, truncated=False ) server = options.get('server_server', None) role_name = options.get('role_servrole', None) status = options.get('status', None) if server is not None: self.obj.ensure_master_exists(server) role_status = self.obj.backend.server_role_search( server_server=server, role_servrole=role_name, status=status) result = [ r for r in role_status if r[u'role_servrole'] != "IPA master"] return dict( result=result, count=len(result), truncated=False, )
class ca_find(LDAPSearch): __doc__ = _("Search for CAs.") msg_summary = ngettext('%(count)d CA matched', '%(count)d CAs matched', 0) def execute(self, *keys, **options): ca_enabled_check(self.api) result = super(ca_find, self).execute(*keys, **options) if not options.get('pkey_only', False): for entry in result['result']: set_certificate_attrs(entry, options, want_cert=False) return result
class idoverrideuser_find(baseidoverride_find): __doc__ = _('Search for an User ID override.') msg_summary = ngettext('%(count)d User ID override matched', '%(count)d User ID overrides matched', 0) def post_callback(self, ldap, entries, truncated, *args, **options): truncated = super(idoverrideuser_find, self).post_callback(ldap, entries, truncated, *args, **options) for entry in entries: convert_sshpubkey_post(ldap, entry.dn, entry) return truncated
class idp_find(LDAPSearch): __doc__ = _('Search for Identity Provider servers.') msg_summary = ngettext('%(count)d Identity Provider server matched', '%(count)d Identity Provider servers matched', 0) def get_options(self): # do not propose --client-id or --secret in ipa idp-find for option in super(idp_find, self).get_options(): if option.name in ('ipaidpclientsecret', 'ipaidpclientid'): option = option.clone(flags={'no_option'}) yield option
def interactive_prompt_callback(self, kw): try: has_cli_options(self, kw, self.no_option_msg, True) except errors.OptionError: pass else: # some record type entered, skip this helper return # get DNS record first so that the NotFound exception is raised # before the helper would start dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result'] self.Backend.textui.print_plain(_("No option to modify specific record provided.")) # ask user for records to be removed self.Backend.textui.print_plain(_(u'Current DNS record contents:\n')) record_params = [] for attr in dns_record: try: param = self.params[attr] except KeyError: continue rrtype = get_record_rrtype(param.name) if not rrtype: continue record_params.append((param, rrtype)) rec_type_content = u', '.join(dns_record[param.name]) self.Backend.textui.print_plain(u'%s: %s' % (param.label, rec_type_content)) self.Backend.textui.print_plain(u'') # ask what records to remove for param, rrtype in record_params: rec_values = list(dns_record[param.name]) for rec_value in dns_record[param.name]: rec_values.remove(rec_value) mod_value = self.Backend.textui.prompt_yesno( _("Modify %(name)s '%(value)s'?") % dict(name=param.label, value=rec_value), default=False) if mod_value is True: user_options = prompt_parts(rrtype, self, mod_dnsvalue=rec_value) kw[param.name] = [rec_value] kw.update(user_options) if rec_values: self.Backend.textui.print_plain(ngettext( u'%(count)d %(type)s record skipped. Only one value per DNS record type can be modified at one time.', u'%(count)d %(type)s records skipped. Only one value per DNS record type can be modified at one time.', 0) % dict(count=len(rec_values), type=rrtype)) break
class fasagreement_find(LDAPSearch): __doc__ = _("Search for User Agreements.") member_attributes = ["member", "memberuser"] has_output_params = ( LDAPSearch.has_output_params + fasagreement_output_params ) msg_summary = ngettext( "%(count)d User Agreement matched", "%(count)d User Agreements matched", 0, )
class idoverridegroup_find(baseidoverride_find): __doc__ = _('Search for an Group ID override.') msg_summary = ngettext('%(count)d Group ID override matched', '%(count)d Group ID overrides matched', 0) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): result = super(idoverridegroup_find, self).pre_callback( ldap, filter, attrs_list, base_dn, scope, *args, **options ) filter, base_dn, scope = result filter = self.obj.filter_for_anchor(ldap, filter, options, 'group') return filter, base_dn, scope
class hostgroup_find(LDAPSearch): __doc__ = _('Search for hostgroups.') member_attributes = ['member', 'memberof'] msg_summary = ngettext('%(count)d hostgroup matched', '%(count)d hostgroups matched', 0) def post_callback(self, ldap, entries, truncated, *args, **options): if options.get('pkey_only', False): return truncated for entry in entries: self.obj.suppress_netgroup_memberof(ldap, entry.dn, entry) return truncated
class automember_find(LDAPSearch): __doc__ = _(""" Search for automember rules. """) takes_options = group_type msg_summary = ngettext( '%(count)d rules matched', '%(count)d rules matched', 0 ) def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options): assert isinstance(base_dn, DN) scope = ldap.SCOPE_SUBTREE ndn = DN(('cn', options['type']), base_dn) return (filters, ndn, scope)
def execute(self, *args, **options): if self.original_msg_summary: object.__setattr__(self, 'msg_summary', self.original_msg_summary) newoptions = {} self.common_enhance_options(newoptions, **options) options.update(newoptions) for arg in args: self.log.debug("user-find- exec arg %r" % (arg)) if options['preserved']: self.obj.container_dn = baseuser.delete_container_dn self.msg_summary = ngettext('%(count)d (delete) user matched', '%(count)d (delete) users matched', 0) ret = super(user_find, self).execute(self, *args, **options) self.obj.container_dn = baseuser.active_container_dn return ret else: return super(user_find, self).execute(self, *args, **options)