diff options
Diffstat (limited to 'ipalib/plugins')
-rw-r--r-- | ipalib/plugins/aci.py | 52 | ||||
-rw-r--r-- | ipalib/plugins/automember.py | 25 | ||||
-rw-r--r-- | ipalib/plugins/automount.py | 6 | ||||
-rw-r--r-- | ipalib/plugins/baseldap.py | 188 | ||||
-rw-r--r-- | ipalib/plugins/config.py | 7 | ||||
-rw-r--r-- | ipalib/plugins/dns.py | 34 | ||||
-rw-r--r-- | ipalib/plugins/entitle.py | 9 | ||||
-rw-r--r-- | ipalib/plugins/group.py | 8 | ||||
-rw-r--r-- | ipalib/plugins/hbacrule.py | 9 | ||||
-rw-r--r-- | ipalib/plugins/host.py | 15 | ||||
-rw-r--r-- | ipalib/plugins/hostgroup.py | 8 | ||||
-rw-r--r-- | ipalib/plugins/krbtpolicy.py | 5 | ||||
-rw-r--r-- | ipalib/plugins/migration.py | 86 | ||||
-rw-r--r-- | ipalib/plugins/netgroup.py | 7 | ||||
-rw-r--r-- | ipalib/plugins/passwd.py | 3 | ||||
-rw-r--r-- | ipalib/plugins/permission.py | 19 | ||||
-rw-r--r-- | ipalib/plugins/pkinit.py | 5 | ||||
-rw-r--r-- | ipalib/plugins/pwpolicy.py | 26 | ||||
-rw-r--r-- | ipalib/plugins/range.py | 8 | ||||
-rw-r--r-- | ipalib/plugins/selinuxusermap.py | 7 | ||||
-rw-r--r-- | ipalib/plugins/service.py | 7 | ||||
-rw-r--r-- | ipalib/plugins/sudorule.py | 16 | ||||
-rw-r--r-- | ipalib/plugins/trust.py | 8 | ||||
-rw-r--r-- | ipalib/plugins/user.py | 18 | ||||
-rw-r--r-- | ipalib/plugins/virtual.py | 3 |
25 files changed, 387 insertions, 192 deletions
diff --git a/ipalib/plugins/aci.py b/ipalib/plugins/aci.py index 7a27ce116..7d5bf504c 100644 --- a/ipalib/plugins/aci.py +++ b/ipalib/plugins/aci.py @@ -123,24 +123,22 @@ from ipalib import api, crud, errors from ipalib import Object, Command from ipalib import Flag, Int, Str, StrEnum from ipalib.aci import ACI -from ipalib.dn import DN from ipalib import output from ipalib import _, ngettext from ipalib.plugins.baseldap import gen_pkey_only_option -if api.env.in_server and api.env.context in ['lite', 'server']: - from ldap import explode_dn from ipapython.ipa_log_manager import * +from ipapython.dn import DN ACI_NAME_PREFIX_SEP = ":" _type_map = { - 'user': 'ldap:///uid=*,%s,%s' % (api.env.container_user, api.env.basedn), - 'group': 'ldap:///cn=*,%s,%s' % (api.env.container_group, api.env.basedn), - 'host': 'ldap:///fqdn=*,%s,%s' % (api.env.container_host, api.env.basedn), - 'hostgroup': 'ldap:///cn=*,%s,%s' % (api.env.container_hostgroup, api.env.basedn), - 'service': 'ldap:///krbprincipalname=*,%s,%s' % (api.env.container_service, api.env.basedn), - 'netgroup': 'ldap:///ipauniqueid=*,%s,%s' % (api.env.container_netgroup, api.env.basedn), - 'dnsrecord': 'ldap:///idnsname=*,%s,%s' % (api.env.container_dns, api.env.basedn), + 'user': 'ldap:///' + str(DN(('uid', '*'), api.env.container_user, api.env.basedn)), + 'group': 'ldap:///' + str(DN(('cn', '*'), api.env.container_group, api.env.basedn)), + 'host': 'ldap:///' + str(DN(('fqdn', '*'), api.env.container_host, api.env.basedn)), + 'hostgroup': 'ldap:///' + str(DN(('cn', '*'), api.env.container_hostgroup, api.env.basedn)), + 'service': 'ldap:///' + str(DN(('krbprincipalname', '*'), api.env.container_service, api.env.basedn)), + 'netgroup': 'ldap:///' + str(DN(('ipauniqueid', '*'), api.env.container_netgroup, api.env.basedn)), + 'dnsrecord': 'ldap:///' + str(DN(('idnsname', '*'), api.env.container_dns, api.env.basedn)), } _valid_permissions_values = [ @@ -247,7 +245,7 @@ def _make_aci(ldap, current, aciname, kw): if 'test' in kw and not kw.get('test'): raise e else: - entry_attrs = {'dn': 'cn=%s,%s' % (kw['permission'], api.env.container_permission)} + entry_attrs = {'dn': DN(('cn', kw['permission']), api.env.container_permission)} elif group: # Not so friendly with groups. This will raise try: @@ -343,10 +341,9 @@ def _aci_to_kw(ldap, a, test=False, pkey_only=False): else: # See if the target is a group. If so we set the # targetgroup attr, otherwise we consider it a subtree - if api.env.container_group in target: - targetdn = unicode(target.replace('ldap:///','')) - target = DN(targetdn) - kw['targetgroup'] = target['cn'] + targetdn = DN(target.replace('ldap:///','')) + if targetdn.endswith(DN(api.env.container_group, api.env.basedn)): + kw['targetgroup'] = targetdn[0]['cn'] else: kw['subtree'] = unicode(target) @@ -357,15 +354,16 @@ def _aci_to_kw(ldap, a, test=False, pkey_only=False): elif groupdn == 'anyone': pass else: - if groupdn.startswith('cn='): - dn = '' + groupdn = DN(groupdn) + if len(groupdn) and groupdn[0].attr == 'cn': + dn = DN() entry_attrs = {} try: (dn, entry_attrs) = ldap.get_entry(groupdn, ['cn']) except errors.NotFound, e: # FIXME, use real name here if test: - dn = 'cn=%s,%s' % ('test', api.env.container_permission) + dn = DN(('cn', 'test'), api.env.container_permission) entry_attrs = {'cn': [u'test']} if api.env.container_permission in dn: kw['permission'] = entry_attrs['cn'][0] @@ -801,11 +799,11 @@ class aci_find(crud.Search): if kw.get('group'): for a in acis: groupdn = a.bindrule['expression'] - groupdn = groupdn.replace('ldap:///','') - cn = None - if groupdn.startswith('cn='): - cn = explode_dn(groupdn)[0] - cn = cn.replace('cn=','') + groupdn = DN(groupdn.replace('ldap:///','')) + try: + cn = groupdn[0]['cn'].value + except (IndexError, KeyError): + cn = None if cn is None or cn != kw['group']: try: results.remove(a) @@ -818,9 +816,11 @@ class aci_find(crud.Search): if 'target' in a.target: target = a.target['target']['expression'] if api.env.container_group in target: - targetdn = unicode(target.replace('ldap:///','')) - cn = explode_dn(targetdn)[0] - cn = cn.replace('cn=','') + targetdn = DN(target.replace('ldap:///','')) + try: + cn = targetdn[0]['cn'] + except (IndexError, KeyError): + cn = None if cn == kw['targetgroup']: found = True if not found: diff --git a/ipalib/plugins/automember.py b/ipalib/plugins/automember.py index 7ccb0bb2f..40359604b 100644 --- a/ipalib/plugins/automember.py +++ b/ipalib/plugins/automember.py @@ -22,8 +22,8 @@ from ipalib import Str, StrEnum from ipalib.plugins.baseldap import * from ipalib import _, ngettext from ipalib.request import context -from ipalib.dn import * import ldap as _ldap +from ipapython.dn import DN __doc__ = _(""" Auto Membership Rule. @@ -200,19 +200,16 @@ class automember(LDAPObject): parent_dn = self.container_dn grouptype = options['type'] try: - ndn = DN(('cn', keys[-1]), ('cn', grouptype), DN(parent_dn)) + ndn = DN(('cn', keys[-1]), ('cn', grouptype), parent_dn) except IndexError: - ndn = DN(('cn', grouptype), DN(parent_dn)) - parent_dn = str(ndn) - return parent_dn + ndn = DN(('cn', grouptype), parent_dn) + return ndn def check_attr(self, attr): """ Verify that the user supplied key is a valid attribute in the schema """ ldap = self.api.Backend.ldap2 - if not ldap.schema: - ldap.get_schema() obj = ldap.schema.get_obj(_ldap.schema.AttributeType, attr) if obj is not None: return obj @@ -238,6 +235,7 @@ class automember_add(LDAPCreate): msg_summary = _('Added automember rule "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) entry_attrs['cn'] = keys[-1] if not automember_container_exists(self.api.Backend.ldap2): @@ -284,6 +282,7 @@ class automember_add_condition(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # Check to see if the automember rule exists try: (tdn, test_attrs) = ldap.get_entry(dn, []) @@ -370,6 +369,7 @@ class automember_remove_condition(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # Check to see if the automember rule exists try: (tdn, test_attrs) = ldap.get_entry(dn, []) @@ -479,10 +479,10 @@ class automember_find(LDAPSearch): ) 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']), DN(base_dn)) - base_dn = str(ndn) - return (filters, base_dn, scope) + ndn = DN(('cn', options['type']), base_dn) + return (filters, ndn, scope) api.register(automember_find) @@ -520,7 +520,6 @@ class automember_default_group_set(LDAPUpdate): def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): dn = DN(('cn', options['type']), api.env.container_automember) - dn = str(dn) entry_attrs['automemberdefaultgroup'] = self.obj.dn_exists(options['type'], options['automemberdefaultgroup']) return dn @@ -542,7 +541,6 @@ class automember_default_group_remove(LDAPUpdate): def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): dn = DN(('cn', options['type']), api.env.container_automember) - dn = str(dn) attr = 'automemberdefaultgroup' (dn, entry_attrs_) = ldap.get_entry( @@ -556,6 +554,7 @@ class automember_default_group_remove(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'automemberdefaultgroup' not in entry_attrs: entry_attrs['automemberdefaultgroup'] = unicode(_('No default (fallback) group set')) return dn @@ -576,10 +575,10 @@ class automember_default_group_show(LDAPRetrieve): def pre_callback(self, ldap, dn, attrs_list, *keys, **options): dn = DN(('cn', options['type']), api.env.container_automember) - dn = str(dn) return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'automemberdefaultgroup' not in entry_attrs: entry_attrs['automemberdefaultgroup'] = unicode(_('No default (fallback) group set')) return dn diff --git a/ipalib/plugins/automount.py b/ipalib/plugins/automount.py index 5c9f42b4c..8e9eb5745 100644 --- a/ipalib/plugins/automount.py +++ b/ipalib/plugins/automount.py @@ -227,6 +227,7 @@ class automountlocation_add(LDAPCreate): msg_summary = _('Added automount location "%(value)s"') def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) # create auto.master for the new location self.api.Command['automountmap_add'](keys[-1], u'auto.master') @@ -595,6 +596,7 @@ class automountmap_del(LDAPDelete): msg_summary = _('Deleted automount map "%(value)s"') def post_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) # delete optional parental connection (direct maps may not have this) try: (dn_, entry_attrs) = ldap.find_entry_by_attr( @@ -718,7 +720,7 @@ class automountkey(LDAPObject): (kwargs['automountkey'], kwargs['automountinformation']) else: sfilter = '(automountkey=%s)' % kwargs['automountkey'] - basedn = 'automountmapname=%s,cn=%s,%s' % (parent_keys[1], parent_keys[0], self.container_dn) + basedn = DN(('automountmapname', parent_keys[1]), ('cn', parent_keys[0]), self.container_dn) attrs_list = ['*'] (entries, truncated) = ldap.find_entries(sfilter, attrs_list, basedn, _ldap.SCOPE_ONELEVEL) @@ -790,6 +792,7 @@ class automountkey_add(LDAPCreate): internal_options = ['description', 'add_operation'] def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) options.pop('add_operation', None) options.pop('description', None) self.obj.check_key_uniqueness(keys[-2], keys[-1], **options) @@ -926,6 +929,7 @@ class automountkey_mod(LDAPUpdate): yield key def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'newautomountkey' in options: entry_attrs['automountkey'] = options['newautomountkey'] if 'newautomountinformation' in options: diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index 32dae5160..e05f59ff4 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -34,7 +34,7 @@ from ipalib.cli import to_cli, from_cli from ipalib import output from ipalib.text import _ from ipalib.util import json_serialize, validate_hostname -from ipalib.dn import * +from ipapython.dn import DN, RDN global_output_params = ( Flag('has_password', @@ -200,6 +200,7 @@ def validate_attribute(ugettext, name, attr): raise errors.ValidationError(name=name, error='Invalid format. Should be name=value') def get_effective_rights(ldap, dn, attrs=None): + assert isinstance(dn, DN) if attrs is None: attrs = ['*', 'nsaccountlock', 'cospriority'] rights = ldap.get_effective_rights(dn, attrs) @@ -332,6 +333,7 @@ def add_external_pre_callback(membertype, ldap, dn, keys, options): membertype is the type of member """ + assert isinstance(dn, DN) # validate hostname with allowed underscore characters, non-fqdn # hostnames are allowed def validate_host(hostname): @@ -361,12 +363,14 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl membertype is the type of member: user, externalattr is one of externaluser, """ + assert isinstance(dn, DN) completed_external = 0 normalize = options.get('external_callback_normalize', True) # Sift through the failures. We assume that these are all # entries that aren't stored in IPA, aka external entries. if memberattr in failed and membertype in failed[memberattr]: (dn, entry_attrs_) = ldap.get_entry(dn, [externalattr]) + assert isinstance(dn, DN) members = entry_attrs.get(memberattr, []) external_entries = entry_attrs_.get(externalattr, []) lc_external_entries = set(e.lower() for e in external_entries) @@ -374,6 +378,7 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl for entry in failed[memberattr][membertype]: membername = entry[0].lower() member_dn = api.Object[membertype].get_dn(membername) + assert isinstance(member_dn, DN) if (membername not in lc_external_entries and member_dn not in members): # Not an IPA entry, assume external @@ -406,6 +411,7 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl return (completed + completed_external, dn) def remove_external_post_callback(memberattr, membertype, externalattr, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) # Run through the failures and gracefully remove any member defined # as an external member. if memberattr in failed and membertype in failed[memberattr]: @@ -440,7 +446,7 @@ def host_is_master(ldap, fqdn): Raises an exception if a master, otherwise returns nothing. """ - master_dn = str(DN('cn=%s' % fqdn, 'cn=masters,cn=ipa,cn=etc', api.env.basedn)) + master_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) try: (dn, entry_attrs) = ldap.get_entry(master_dn, ['objectclass']) raise errors.ValidationError(name='hostname', error=_('An IPA master host cannot be deleted or disabled')) @@ -518,9 +524,11 @@ class LDAPObject(Object): return self.backend.make_dn_from_attr( self.primary_key.name, keys[-1], parent_dn ) + assert isinstance(parent_dn, DN) return parent_dn def get_primary_key_from_dn(self, dn): + assert isinstance(dn, DN) try: if self.rdn_attribute: (dn, entry_attrs) = self.backend.get_entry( @@ -532,8 +540,6 @@ class LDAPObject(Object): return '' except errors.NotFound: pass - # DN object assures we're returning a decoded (unescaped) value - dn = DN(dn) try: return dn[self.primary_key.name] except KeyError: @@ -567,7 +573,7 @@ class LDAPObject(Object): for member in entry_attrs.setdefault(attr, []): for ldap_obj_name in self.attribute_members[attr]: ldap_obj = self.api.Object[ldap_obj_name] - if member.find(ldap_obj.container_dn) > 0: + if ldap_obj.container_dn in member: new_attr = '%s_%s' % (attr, ldap_obj.name) entry_attrs.setdefault(new_attr, []).append( ldap_obj.get_primary_key_from_dn(member) @@ -623,7 +629,6 @@ class LDAPObject(Object): def __json__(self): ldap = self.backend - ldap.get_schema() json_dict = dict( (a, getattr(self, a)) for a in self.json_friendly_attributes ) @@ -777,52 +782,47 @@ last, after all sets and adds."""), _callback_registry = dict(pre={}, post={}, exc={}, interactive_prompt={}) - def _convert_2_dict(self, attrs): + def _convert_2_dict(self, ldap, attrs): """ Convert a string in the form of name/value pairs into a dictionary. :param attrs: A list of name/value pair strings, in the "name=value" format. May also be a single string, or None. """ - if attrs is None: - return {} - - if not isinstance(attrs, (tuple, list)): - attrs = [attrs] newdict = {} + if attrs is None: + attrs = [] + elif not type(attrs) in (list, tuple): + attrs = [attrs] for a in attrs: - m = re.match("^\s*(?P<attr>.*?)\s*=\s*(?P<value>.*?)\s*$", a) - attr = str(m.group('attr').lower()) - value = m.group('value') - + m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", a) + attr = str(m.group(1)).lower() + value = m.group(2) if attr in self.obj.params and attr not in self.params: # The attribute is managed by IPA, but it didn't get cloned # to the command. This happens with no_update/no_create attrs. raise errors.ValidationError( name=attr, error=_('attribute is not configurable')) + if len(value) == 0: + # None means "delete this attribute" + value = None - newdict.setdefault(attr, []).append(value) + if ldap.has_dn_syntax(attr): + value = DN(value) + if attr in newdict: + if type(value) in (tuple,): + newdict[attr] += list(value) + else: + newdict[attr].append(value) + else: + if type(value) in (tuple,): + newdict[attr] = list(value) + else: + newdict[attr] = [value] return newdict - def _convert_entry(self, entry_attrs): - result = {} - for attr, val in entry_attrs.iteritems(): - if val is None: - val = [] - elif not isinstance(val, (tuple, list)): - val = [val] - - result[attr] = [] - for v in val: - if isinstance(v, str): - # This is a Binary value, base64 encode it - v = base64.b64encode(v) - result[attr].append(unicode(v)) - - return result - def process_attr_options(self, entry_attrs, dn, keys, options): """ Process all --setattr, --addattr, and --delattr options and add the @@ -847,14 +847,15 @@ last, after all sets and adds."""), :param keys: List of command arguments :param options: List of options """ + if all(k not in options for k in ("setattr", "addattr", "delattr")): return ldap = self.obj.backend - adddict = self._convert_2_dict(options.get('addattr', [])) - setdict = self._convert_2_dict(options.get('setattr', [])) - deldict = self._convert_2_dict(options.get('delattr', [])) + adddict = self._convert_2_dict(ldap, options.get('addattr', [])) + setdict = self._convert_2_dict(ldap, options.get('setattr', [])) + deldict = self._convert_2_dict(ldap, options.get('delattr', [])) setattrs = set(setdict.keys()) addattrs = set(adddict.keys()) @@ -865,24 +866,24 @@ last, after all sets and adds."""), direct_del = delattrs needldapattrs = [] else: + assert isinstance(dn, DN) direct_add = setattrs & addattrs direct_del = setattrs & delattrs needldapattrs = list((addattrs | delattrs) - setattrs) - mod_attrs = self._convert_entry(entry_attrs) - for attr, val in setdict.iteritems(): - mod_attrs[attr] = val + entry_attrs[attr] = val for attr in direct_add: - mod_attrs.setdefault(attr, []).extend(adddict[attr]) + entry_attrs.setdefault(attr, []).extend(adddict[attr]) for attr in direct_del: for delval in deldict[attr]: try: - mod_attrs[attr].remove(delval) + entry_attrs[attr].remove(delval) except ValueError: - raise errors.AttrValueNotFound(attr=attr, value=delval) + raise errors.AttrValueNotFound(attr=attr, + value=delval) if needldapattrs: try: @@ -901,27 +902,28 @@ last, after all sets and adds."""), raise errors.ValidationError(name=del_nonexisting.pop(), error=_('No such attribute on this entry')) - old_entry = self._convert_entry(old_entry) - for attr in needldapattrs: - mod_attrs[attr] = old_entry.get(attr, []) + entry_attrs[attr] = old_entry.get(attr, []) if attr in addattrs: - mod_attrs[attr].extend(adddict.get(attr, [])) + entry_attrs[attr].extend(adddict.get(attr, [])) for delval in deldict.get(attr, []): try: - mod_attrs[attr].remove(delval) + entry_attrs[attr].remove(delval) except ValueError: + if isinstance(delval, str): + # This is a Binary value, base64 encode it + delval = unicode(base64.b64encode(delval)) raise errors.AttrValueNotFound(attr=attr, value=delval) # normalize all values changedattrs = setattrs | addattrs | delattrs for attr in changedattrs: - value = mod_attrs[attr] if attr in self.params and self.params[attr].attribute: - param = self.params[attr] # convert single-value params to scalars + param = self.params[attr] + value = entry_attrs[attr] if not param.multivalue: if len(value) == 1: value = value[0] @@ -931,19 +933,19 @@ last, after all sets and adds."""), raise errors.OnlyOneValueAllowed(attr=attr) # validate, convert and encode params try: - value = param(value) + value = param(value) except errors.ValidationError, err: raise errors.ValidationError(name=attr, error=err.error) except errors.ConversionError, err: raise errors.ConversionError(name=attr, error=err.error) + entry_attrs[attr] = value else: # unknown attribute: remove duplicite and invalid values - value = list(set([val for val in value if val])) - if not value: - value = None - elif isinstance(value, (tuple, list)) and len(value) == 1: - value = value[0] - entry_attrs[attr] = value + entry_attrs[attr] = list(set([val for val in entry_attrs[attr] if val])) + if not entry_attrs[attr]: + entry_attrs[attr] = None + elif isinstance(entry_attrs[attr], (tuple, list)) and len(entry_attrs[attr]) == 1: + entry_attrs[attr] = entry_attrs[attr][0] @classmethod def register_pre_callback(cls, callback, first=False): @@ -1021,8 +1023,13 @@ class LDAPCreate(BaseLDAPCommand, crud.Create): entry_attrs[self.obj.uuid_attribute] = 'autogenerate' dn = self.obj.get_dn(*keys, **options) + assert isinstance(dn, DN) if self.obj.rdn_attribute: - if not dn.startswith('%s=' % self.obj.primary_key.name): + try: + dn_attr = dn[0].attr + except (IndexError, KeyError): + dn_attr = None + if dn_attr != self.obj.primary_key.name: self.obj.handle_duplicate_entry(*keys) dn = ldap.make_dn( entry_attrs, self.obj.rdn_attribute, self.obj.container_dn @@ -1038,9 +1045,9 @@ class LDAPCreate(BaseLDAPCommand, crud.Create): for callback in self.get_callbacks('pre'): dn = callback( self, ldap, dn, entry_attrs, attrs_list, *keys, **options) + assert isinstance(dn, DN) _check_single_value_attrs(self.params, entry_attrs) - ldap.get_schema() _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True) _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False) @@ -1074,16 +1081,19 @@ class LDAPCreate(BaseLDAPCommand, crud.Create): self.obj.primary_key.name, keys[-1], object_class, attrs_list, self.obj.container_dn ) + assert isinstance(dn, DN) else: (dn, entry_attrs) = self._exc_wrapper(keys, options, ldap.get_entry)( dn, attrs_list, normalize=self.obj.normalize_dn ) + assert isinstance(dn, DN) except errors.NotFound: self.obj.handle_not_found(*keys) for callback in self.get_callbacks('post'): dn = callback(self, ldap, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) entry_attrs['dn'] = dn self.obj.convert_attribute_members(entry_attrs, *keys, **options) @@ -1092,9 +1102,11 @@ class LDAPCreate(BaseLDAPCommand, crud.Create): return dict(result=entry_attrs, value=u'') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return dn def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1181,6 +1193,7 @@ class LDAPRetrieve(LDAPQuery): ldap = self.obj.backend dn = self.obj.get_dn(*keys, **options) + assert isinstance(dn, DN) if options.get('all', False): attrs_list = ['*'] + self.obj.default_attributes @@ -1189,11 +1202,13 @@ class LDAPRetrieve(LDAPQuery): for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, attrs_list, *keys, **options) + assert isinstance(dn, DN) try: (dn, entry_attrs) = self._exc_wrapper(keys, options, ldap.get_entry)( dn, attrs_list, normalize=self.obj.normalize_dn ) + assert isinstance(dn, DN) except errors.NotFound: self.obj.handle_not_found(*keys) @@ -1202,17 +1217,21 @@ class LDAPRetrieve(LDAPQuery): for callback in self.get_callbacks('post'): dn = callback(self, ldap, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) self.obj.convert_attribute_members(entry_attrs, *keys, **options) + assert isinstance(dn, DN) entry_attrs['dn'] = dn if self.obj.primary_key and keys[-1] is not None: return dict(result=entry_attrs, value=keys[-1]) return dict(result=entry_attrs, value=u'') def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return dn def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1261,6 +1280,7 @@ class LDAPUpdate(LDAPQuery, crud.Update): raise errors.EmptyModlist() dn = self.obj.get_dn(*keys, **options) + assert isinstance(dn, DN) entry_attrs = self.args_options_2_entry(**options) @@ -1279,8 +1299,8 @@ class LDAPUpdate(LDAPQuery, crud.Update): for callback in self.get_callbacks('pre'): dn = callback( self, ldap, dn, entry_attrs, attrs_list, *keys, **options) + assert isinstance(dn, DN) - ldap.get_schema() _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True) _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False) @@ -1294,10 +1314,10 @@ class LDAPUpdate(LDAPQuery, crud.Update): if self.obj.rdn_is_primary_key and self.obj.primary_key.name in entry_attrs: # RDN change self._exc_wrapper(keys, options, ldap.update_entry_rdn)(dn, - unicode('%s=%s' % (self.obj.primary_key.name, - entry_attrs[self.obj.primary_key.name]))) + RDN((self.obj.primary_key.name, entry_attrs[self.obj.primary_key.name]))) rdnkeys = keys[:-1] + (entry_attrs[self.obj.primary_key.name], ) dn = self.obj.get_dn(*rdnkeys) + assert isinstance(dn, DN) del entry_attrs[self.obj.primary_key.name] options['rdnupdate'] = True rdnupdate = True @@ -1306,6 +1326,7 @@ class LDAPUpdate(LDAPQuery, crud.Update): # to decide what to do. An EmptyModlist in this context doesn't # mean an error occurred, just that there were no other updates to # perform. + assert isinstance(dn, DN) self._exc_wrapper(keys, options, ldap.update_entry)(dn, entry_attrs, normalize=self.obj.normalize_dn) except errors.EmptyModlist, e: if not rdnupdate: @@ -1327,6 +1348,7 @@ class LDAPUpdate(LDAPQuery, crud.Update): for callback in self.get_callbacks('post'): dn = callback(self, ldap, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) self.obj.convert_attribute_members(entry_attrs, *keys, **options) if self.obj.primary_key and keys[-1] is not None: @@ -1334,9 +1356,11 @@ class LDAPUpdate(LDAPQuery, crud.Update): return dict(result=entry_attrs, value=u'') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return dn def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1360,11 +1384,14 @@ class LDAPDelete(LDAPMultiQuery): def delete_entry(pkey): nkeys = keys[:-1] + (pkey, ) dn = self.obj.get_dn(*nkeys, **options) + assert isinstance(dn, DN) for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, *nkeys, **options) + assert isinstance(dn, DN) def delete_subtree(base_dn): + assert isinstance(base_dn, DN) truncated = True while truncated: try: @@ -1412,9 +1439,11 @@ class LDAPDelete(LDAPMultiQuery): return dict(result=dict(failed=u''), value=u'') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) return True def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1495,14 +1524,17 @@ class LDAPAddMember(LDAPModMember): (member_dns, failed) = self.get_member_dns(**options) dn = self.obj.get_dn(*keys, **options) + assert isinstance(dn, DN) for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, member_dns, failed, *keys, **options) + assert isinstance(dn, DN) completed = 0 for (attr, objs) in member_dns.iteritems(): for ldap_obj_name in objs: for m_dn in member_dns[attr][ldap_obj_name]: + assert isinstance(m_dn, DN) if not m_dn: continue try: @@ -1534,7 +1566,9 @@ class LDAPAddMember(LDAPModMember): (completed, dn) = callback( self, ldap, completed, failed, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) + assert isinstance(dn, DN) entry_attrs['dn'] = dn self.obj.convert_attribute_members(entry_attrs, *keys, **options) return dict( @@ -1544,9 +1578,11 @@ class LDAPAddMember(LDAPModMember): ) def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return (completed, dn) def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1583,14 +1619,17 @@ class LDAPRemoveMember(LDAPModMember): (member_dns, failed) = self.get_member_dns(**options) dn = self.obj.get_dn(*keys, **options) + assert isinstance(dn, DN) for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, member_dns, failed, *keys, **options) + assert isinstance(dn, DN) completed = 0 for (attr, objs) in member_dns.iteritems(): for ldap_obj_name, m_dns in objs.iteritems(): for m_dn in m_dns: + assert isinstance(m_dn, DN) if not m_dn: continue try: @@ -1625,7 +1664,9 @@ class LDAPRemoveMember(LDAPModMember): (completed, dn) = callback( self, ldap, completed, failed, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) + assert isinstance(dn, DN) entry_attrs['dn'] = dn self.obj.convert_attribute_members(entry_attrs, *keys, **options) @@ -1636,9 +1677,11 @@ class LDAPRemoveMember(LDAPModMember): ) def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return (completed, dn) def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -1765,6 +1808,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search): base_dn = self.api.Object[self.obj.parent_object].get_dn(*args[:-1]) else: base_dn = self.obj.container_dn + assert isinstance(base_dn, DN) search_kw = self.args_options_2_entry(**options) @@ -1812,6 +1856,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search): for callback in self.get_callbacks('pre'): (filter, base_dn, scope) = callback( self, ldap, filter, attrs_list, base_dn, scope, *args, **options) + assert isinstance(base_dn, DN) try: (entries, truncated) = self._exc_wrapper(args, options, ldap.find_entries)( @@ -1827,14 +1872,16 @@ class LDAPSearch(BaseLDAPCommand, crud.Search): if self.sort_result_entries: if self.obj.primary_key: - sortfn=lambda x,y: cmp(x[1][self.obj.primary_key.name][0].lower(), y[1][self.obj.primary_key.name][0].lower()) - entries.sort(sortfn) + def sort_key(x): + return x[1][self.obj.primary_key.name][0].lower() + entries.sort(key=sort_key) if not options.get('raw', False): for e in entries: self.obj.convert_attribute_members(e[1], *args, **options) for e in entries: + assert isinstance(e[0], DN) e[1]['dn'] = e[0] entries = [e for (dn, e) in entries] @@ -1845,6 +1892,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search): ) def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) return (filters, base_dn, scope) def post_callback(self, ldap, entries, truncated, *args, **options): @@ -1926,9 +1974,11 @@ class LDAPAddReverseMember(LDAPModReverseMember): # Ensure our target exists result = self.api.Command[self.show_command](keys[-1])['result'] dn = result['dn'] + assert isinstance(dn, DN) for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, *keys, **options) + assert isinstance(dn, DN) if options.get('all', False): attrs_list = ['*'] + self.obj.default_attributes @@ -1967,7 +2017,9 @@ class LDAPAddReverseMember(LDAPModReverseMember): (completed, dn) = callback( self, ldap, completed, failed, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) + assert isinstance(dn, DN) entry_attrs['dn'] = dn return dict( completed=completed, @@ -1976,9 +2028,11 @@ class LDAPAddReverseMember(LDAPModReverseMember): ) def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return (completed, dn) def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -2022,9 +2076,11 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): # Ensure our target exists result = self.api.Command[self.show_command](keys[-1])['result'] dn = result['dn'] + assert isinstance(dn, DN) for callback in self.get_callbacks('pre'): dn = callback(self, ldap, dn, *keys, **options) + assert isinstance(dn, DN) if options.get('all', False): attrs_list = ['*'] + self.obj.default_attributes @@ -2063,7 +2119,9 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): (completed, dn) = callback( self, ldap, completed, failed, dn, entry_attrs, *keys, **options) + assert isinstance(dn, DN) + assert isinstance(dn, DN) entry_attrs['dn'] = dn return dict( completed=completed, @@ -2072,9 +2130,11 @@ class LDAPRemoveReverseMember(LDAPModReverseMember): ) def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) return dn def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return (completed, dn) def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): diff --git a/ipalib/plugins/config.py b/ipalib/plugins/config.py index 9573bbb65..ef0fd79fa 100644 --- a/ipalib/plugins/config.py +++ b/ipalib/plugins/config.py @@ -19,7 +19,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from ipalib import api -from ipalib import Bool, Int, Str, IA5Str, StrEnum +from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam from ipalib.plugins.baseldap import * from ipalib import _ from ipalib.errors import ValidationError @@ -149,7 +149,7 @@ class config(LDAPObject): label=_('Enable migration mode'), doc=_('Enable migration mode'), ), - Str('ipacertificatesubjectbase', + DNParam('ipacertificatesubjectbase', cli_name='subject', label=_('Certificate Subject base'), doc=_('Base for certificate subjects (OU=Test,O=Example)'), @@ -199,7 +199,7 @@ class config(LDAPObject): ) def get_dn(self, *keys, **kwargs): - return 'cn=ipaconfig,cn=etc' + return DN(('cn', 'ipaconfig'), ('cn', 'etc')) api.register(config) @@ -208,6 +208,7 @@ class config_mod(LDAPUpdate): __doc__ = _('Modify configuration options.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if 'ipadefaultprimarygroup' in entry_attrs: group=entry_attrs['ipadefaultprimarygroup'] try: diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index 6727d052f..991eb0164 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -35,7 +35,6 @@ from ipalib.util import (validate_zonemgr, normalize_zonemgr, validate_hostname, validate_dns_label, validate_domain_name, get_dns_forward_zone_update_policy, get_dns_reverse_zone_update_policy) from ipapython.ipautil import valid_ip, CheckedIPAddress, is_host_resolvable -from ldap import explode_dn __doc__ = _(""" Domain Name System (DNS) @@ -802,10 +801,10 @@ class DNSRecord(Str): # callbacks for per-type special record behavior def dnsrecord_add_pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - pass + assert isinstance(dn, DN) def dnsrecord_add_post_callback(self, ldap, dn, entry_attrs, *keys, **options): - pass + assert isinstance(dn, DN) class ForwardRecord(DNSRecord): extra = ( @@ -817,6 +816,7 @@ class ForwardRecord(DNSRecord): ) def dnsrecord_add_pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) reverse_option = self._convert_dnsrecord_extra(self.extra[0]) if options.get(reverse_option.name): records = entry_attrs.get(self.name, []) @@ -832,6 +832,7 @@ class ForwardRecord(DNSRecord): setattr(context, '%s_reverse' % self.name, entry_attrs.get(self.name)) def dnsrecord_add_post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) rev_records = getattr(context, '%s_reverse' % self.name, []) if rev_records: @@ -1727,6 +1728,7 @@ class dnszone_add(LDAPCreate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if not dns_container_exists(self.api.Backend.ldap2): raise errors.NotFound(reason=_('DNS is not configured')) @@ -1751,6 +1753,7 @@ class dnszone_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'ip_address' in options: nameserver = entry_attrs['idnssoamname'][0][:-1] # ends with a dot nsparts = nameserver.split('.') @@ -1813,6 +1816,7 @@ class dnszone_find(LDAPSearch): ) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) if options.get('forward_only', False): search_kw = {} search_kw['idnsname'] = _valid_reverse_zones.keys() @@ -1980,6 +1984,7 @@ class dnsrecord(LDAPObject): ) def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) nsrecords = entry_attrs.get('nsrecord') if options.get('force', False) or nsrecords is None: return @@ -1987,6 +1992,7 @@ class dnsrecord(LDAPObject): check_ns_rec_resolvable(keys[0], nsrecord) def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) ptrrecords = entry_attrs.get('ptrrecord') if ptrrecords is None: return @@ -2015,6 +2021,7 @@ class dnsrecord(LDAPObject): % dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count))) def run_precallback_validators(self, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) ldap = self.api.Backend.ldap2 for rtype in entry_attrs: @@ -2049,7 +2056,7 @@ class dnsrecord(LDAPObject): def get_dns_masters(self): ldap = self.api.Backend.ldap2 - base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % self.api.env.basedn + base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), self.api.env.basedn) ldap_filter = '(&(objectClass=ipaConfigObject)(cn=DNS))' dns_masters = [] @@ -2058,9 +2065,12 @@ class dnsrecord(LDAPObject): for entry in entries: master_dn = entry[0] - if master_dn.startswith('cn='): - master = explode_dn(master_dn)[1].replace('cn=','') + assert isinstance(master_dn, DN) + try: + master = master_dn[1]['cn'] dns_masters.append(master) + except (IndexError, KeyError): + pass except errors.NotFound: return [] @@ -2254,6 +2264,7 @@ class dnsrecord_add(LDAPCreate): kw.update(user_options) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) precallback_attrs = [] processed_attrs = [] for option in options: @@ -2354,6 +2365,7 @@ class dnsrecord_add(LDAPCreate): raise exc def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) for attr in getattr(context, 'dnsrecord_precallback_attrs', []): param = self.params[attr] param.dnsrecord_add_post_callback(ldap, dn, entry_attrs, *keys, **options) @@ -2382,6 +2394,7 @@ class dnsrecord_mod(LDAPUpdate): return super(dnsrecord_mod, self).args_options_2_entry(*keys, **options) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if options.get('rename') and self.obj.is_pkey_zone_record(*keys): # zone rename is not allowed raise errors.ValidationError(name='rename', @@ -2466,10 +2479,12 @@ class dnsrecord_mod(LDAPUpdate): return result def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if self.obj.is_pkey_zone_record(*keys): entry_attrs[self.obj.primary_key.name] = [_dns_zone_record] self.obj.postprocess_record(entry_attrs, **options) + return dn def interactive_prompt_callback(self, kw): try: @@ -2564,6 +2579,7 @@ class dnsrecord_del(LDAPUpdate): yield option def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: (dn_, old_entry) = ldap.get_entry( dn, _record_attributes, @@ -2626,9 +2642,11 @@ class dnsrecord_del(LDAPUpdate): return result def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if self.obj.is_pkey_zone_record(*keys): entry_attrs[self.obj.primary_key.name] = [_dns_zone_record] self.obj.postprocess_record(entry_attrs, **options) + return dn def args_options_2_entry(self, *keys, **options): self.obj.has_cli_options(options, self.no_option_msg) @@ -2697,6 +2715,7 @@ class dnsrecord_show(LDAPRetrieve): ) def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if self.obj.is_pkey_zone_record(*keys): entry_attrs[self.obj.primary_key.name] = [_dns_zone_record] self.obj.postprocess_record(entry_attrs, **options) @@ -2723,6 +2742,7 @@ class dnsrecord_find(LDAPSearch): yield option def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) # include zone record (root entry) in the search return (filter, base_dn, ldap.SCOPE_SUBTREE) @@ -2774,7 +2794,7 @@ class dns_is_enabled(Command): NO_CLI = True has_output = output.standard_value - base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn + base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) filter = '(&(objectClass=ipaConfigObject)(cn=DNS))' def execute(self, *args, **options): diff --git a/ipalib/plugins/entitle.py b/ipalib/plugins/entitle.py index 5ccdb6510..67e7f959e 100644 --- a/ipalib/plugins/entitle.py +++ b/ipalib/plugins/entitle.py @@ -318,6 +318,7 @@ class entitle_consume(LDAPUpdate): return result def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) quantity = keys[-1] os.environ['LANG'] = 'en_US' @@ -361,6 +362,7 @@ class entitle_consume(LDAPUpdate): Returning the certificates isn't very interesting. Return the status of entitlements instead. """ + assert isinstance(dn, DN) if 'usercertificate' in entry_attrs: del entry_attrs['usercertificate'] if 'userpkcs12' in entry_attrs: @@ -504,7 +506,7 @@ class entitle_register(LDAPCreate): """ def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - dn = '%s,%s' % (self.obj.container_dn, self.api.env.basedn) + dn = DN(self.obj.container_dn, self.api.env.basedn) if not ldap.can_add(dn): raise errors.ACIError(info='No permission to register') os.environ['LANG'] = 'en_US' @@ -604,6 +606,7 @@ class entitle_import(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: (db, uuid, certfile, keyfile) = get_uuid(ldap) if db is not None: @@ -622,7 +625,7 @@ class entitle_import(LDAPUpdate): raise errors.CertificateFormatError(error=_('Not an entitlement certificate')) except M2Crypto.X509.X509Error: raise errors.CertificateFormatError(error=_('Not an entitlement certificate')) - dn = 'ipaentitlementid=%s,%s' % (entry_attrs['ipaentitlementid'], dn) + dn = DN(('ipaentitlementid', entry_attrs['ipaentitlementid']), dn) (dn, current_attrs) = ldap.get_entry( dn, ['*'], normalize=self.obj.normalize_dn ) @@ -689,6 +692,7 @@ class entitle_sync(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) os.environ['LANG'] = 'en_US' locale.setlocale(locale.LC_ALL, '') @@ -719,6 +723,7 @@ class entitle_sync(LDAPUpdate): Returning the certificates isn't very interesting. Return the status of entitlements instead. """ + assert isinstance(dn, DN) if 'usercertificate' in entry_attrs: del entry_attrs['usercertificate'] if 'userpkcs12' in entry_attrs: diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py index 74bea1700..011587206 100644 --- a/ipalib/plugins/group.py +++ b/ipalib/plugins/group.py @@ -156,6 +156,7 @@ class group_add(LDAPCreate): # As both 'external' and 'nonposix' options have default= set for # them, they will always be present in options dict, thus we can # safely reference the values + assert isinstance(dn, DN) if options['external']: entry_attrs['objectclass'].append('ipaexternalgroup') if 'gidnumber' in options: @@ -176,6 +177,7 @@ class group_del(LDAPDelete): msg_summary = _('Deleted group "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) config = ldap.get_ipa_config()[1] def_primary_group = config.get('ipadefaultprimarygroup', '') def_primary_group_dn = group_dn = self.obj.get_dn(def_primary_group) @@ -192,6 +194,7 @@ class group_del(LDAPDelete): return dn def post_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) try: api.Command['pwpolicy_del'](keys[-1]) except errors.NotFound: @@ -220,6 +223,7 @@ class group_mod(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if ('posix' in options and options['posix']) or 'gidnumber' in options: (dn, old_entry_attrs) = ldap.get_entry(dn, ['objectclass']) if 'ipaexternalgroup' in old_entry_attrs['objectclass']: @@ -275,6 +279,7 @@ class group_find(LDAPSearch): ) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) # if looking for private groups, we need to create a new search filter, # because private groups have different object classes if options['private']: @@ -319,6 +324,7 @@ class group_add_member(LDAPAddMember): ) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) result = (completed, dn) if 'ipaexternalmember' in options: if not _dcerpc_bindings_installed: @@ -367,6 +373,7 @@ class group_remove_member(LDAPRemoveMember): ) def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) if keys[0] == protected_group_name: result = api.Command.group_show(protected_group_name) users_left = set(result['result'].get('member_user', [])) @@ -377,6 +384,7 @@ class group_remove_member(LDAPRemoveMember): return dn def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) result = (completed, dn) if 'ipaexternalmember' in options: sids = options['ipaexternalmember'] diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py index 460083622..94f0d0e20 100644 --- a/ipalib/plugins/hbacrule.py +++ b/ipalib/plugins/hbacrule.py @@ -231,6 +231,7 @@ class hbacrule_add(LDAPCreate): msg_summary = _('Added HBAC rule "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # HBAC rules are enabled by default entry_attrs['ipaenabledflag'] = 'TRUE' return dn @@ -244,6 +245,7 @@ class hbacrule_del(LDAPDelete): msg_summary = _('Deleted HBAC rule "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) kw = dict(seealso=keys[0]) _entries = api.Command.selinuxusermap_find(None, **kw) if _entries['count']: @@ -260,6 +262,7 @@ class hbacrule_mod(LDAPUpdate): msg_summary = _('Modified HBAC rule "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, attrs_list) except errors.NotFound: @@ -436,6 +439,7 @@ class hbacrule_add_user(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -464,6 +468,7 @@ class hbacrule_add_host(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -492,6 +497,7 @@ class hbacrule_add_sourcehost(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -502,6 +508,7 @@ class hbacrule_add_sourcehost(LDAPAddMember): return add_external_pre_callback('host', ldap, dn, keys, options) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('sourcehost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(hbacrule_add_sourcehost) @@ -514,6 +521,7 @@ class hbacrule_remove_sourcehost(LDAPRemoveMember): member_count_out = ('%i object removed.', '%i objects removed.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('sourcehost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(hbacrule_remove_sourcehost) @@ -526,6 +534,7 @@ class hbacrule_add_service(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index e8967b8c0..a417ba0f7 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -38,10 +38,10 @@ from ipalib.plugins.dns import (dns_container_exists, _record_types, from ipalib.plugins.dns import get_reverse_zone from ipalib import _, ngettext from ipalib import x509 -from ipalib.dn import * from ipalib.request import context from ipalib.util import validate_sshpubkey, output_sshpubkey from ipapython.ipautil import ipa_generate_password, CheckedIPAddress, make_sshfp +from ipapython.dn import DN __doc__ = _(""" Hosts/Machines @@ -379,6 +379,7 @@ class host_add(LDAPCreate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if options.get('ip_address') and dns_container_exists(ldap): parts = keys[-1].split('.') host = parts[0] @@ -423,6 +424,7 @@ class host_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) exc = None if dns_container_exists(ldap): try: @@ -483,6 +485,7 @@ class host_del(LDAPDelete): ) def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) # If we aren't given a fqdn, find it if _hostname_validator(None, keys[-1]) is not None: hostentry = api.Command['host_show'](keys[-1])['result'] @@ -599,6 +602,7 @@ class host_mod(LDAPUpdate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # Allow an existing OTP to be reset but don't allow a OTP to be # added to an enrolled host. if options.get('userpassword') or options.get('random'): @@ -690,6 +694,7 @@ class host_mod(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if options.get('random', False): entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword')) set_certificate_attrs(entry_attrs) @@ -728,6 +733,7 @@ class host_find(LDAPSearch): yield option def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) if 'locality' in attrs_list: attrs_list.remove('locality') attrs_list.append('l') @@ -808,6 +814,7 @@ class host_show(LDAPRetrieve): member_attributes = ['managedby'] def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.get_password_attributes(ldap, dn, entry_attrs) if entry_attrs['has_password']: # If an OTP is set there is no keytab, at least not one @@ -891,8 +898,7 @@ class host_disable(LDAPQuery): try: serial = unicode(x509.get_serial_number(cert, x509.DER)) try: - result = api.Command['cert_show'](unicode(serial))['result' -] + result = api.Command['cert_show'](unicode(serial))['result'] if 'revocation_reason' not in result: try: api.Command['cert_revoke'](unicode(serial), revocation_reason=4) @@ -928,6 +934,7 @@ class host_disable(LDAPQuery): ) def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(entry_attrs) return dn @@ -941,6 +948,7 @@ class host_add_managedby(LDAPAddMember): allow_same = True def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(entry_attrs) return (completed, dn) @@ -954,6 +962,7 @@ class host_remove_managedby(LDAPRemoveMember): has_output_params = LDAPRemoveMember.has_output_params + host_output_params def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(entry_attrs) return (completed, dn) diff --git a/ipalib/plugins/hostgroup.py b/ipalib/plugins/hostgroup.py index b68c45842..7e6fe6d65 100644 --- a/ipalib/plugins/hostgroup.py +++ b/ipalib/plugins/hostgroup.py @@ -21,7 +21,7 @@ from ipalib.plugins.baseldap import * from ipalib import api, Int, _, ngettext, errors from ipalib.plugins.netgroup import NETGROUP_PATTERN, NETGROUP_PATTERN_ERRMSG -from ipalib.dn import DN +from ipapython.dn import DN __doc__ = _(""" Groups of hosts. @@ -119,6 +119,7 @@ class hostgroup_add(LDAPCreate): msg_summary = _('Added hostgroup "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: # check duplicity with hostgroups first to provide proper error netgroup = api.Command['hostgroup_show'](keys[-1]) @@ -140,6 +141,7 @@ class hostgroup_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) # Always wait for the associated netgroup to be created so we can # be sure to ignore it in memberOf newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry') @@ -166,6 +168,7 @@ class hostgroup_mod(LDAPUpdate): msg_summary = _('Modified hostgroup "%(value)s"') def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(dn, entry_attrs) return dn @@ -195,6 +198,7 @@ class hostgroup_show(LDAPRetrieve): __doc__ = _('Display information about a hostgroup.') def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof( dn, entry_attrs) return dn @@ -205,6 +209,7 @@ class hostgroup_add_member(LDAPAddMember): __doc__ = _('Add members to a hostgroup.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(dn, entry_attrs) return (completed, dn) @@ -215,6 +220,7 @@ class hostgroup_remove_member(LDAPRemoveMember): __doc__ = _('Remove members from a hostgroup.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.suppress_netgroup_memberof(dn, entry_attrs) return (completed, dn) diff --git a/ipalib/plugins/krbtpolicy.py b/ipalib/plugins/krbtpolicy.py index 0f80c770c..60674cc06 100644 --- a/ipalib/plugins/krbtpolicy.py +++ b/ipalib/plugins/krbtpolicy.py @@ -71,7 +71,7 @@ class krbtpolicy(LDAPObject): """ Kerberos Ticket Policy object """ - container_dn = 'cn=%s,cn=kerberos' % api.env.realm + container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos')) object_name = _('kerberos ticket policy settings') default_attributes = ['krbmaxticketlife', 'krbmaxrenewableage'] limit_object_classes = ['krbticketpolicyaux'] @@ -112,6 +112,7 @@ class krbtpolicy_mod(LDAPUpdate): __doc__ = _('Modify Kerberos ticket policy.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # disable all flag # ticket policies are attached to objects with unrelated attributes if options.get('all'): @@ -125,6 +126,7 @@ class krbtpolicy_show(LDAPRetrieve): __doc__ = _('Display the current Kerberos ticket policy.') def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + assert isinstance(dn, DN) # disable all flag # ticket policies are attached to objects with unrelated attributes if options.get('all'): @@ -132,6 +134,7 @@ class krbtpolicy_show(LDAPRetrieve): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if keys[-1] is not None: # if policy for a specific user isn't set, display global values if 'krbmaxticketlife' not in entry_attrs or \ diff --git a/ipalib/plugins/migration.py b/ipalib/plugins/migration.py index a8c1c6d82..157ab4447 100644 --- a/ipalib/plugins/migration.py +++ b/ipalib/plugins/migration.py @@ -21,10 +21,8 @@ import re import ldap as _ldap from ipalib import api, errors, output -from ipalib import Command, Password, Str, Flag, StrEnum +from ipalib import Command, Password, Str, Flag, StrEnum, DNParam from ipalib.cli import to_cli -from ipalib.util import validate_dn_param -from ipalib.dn import * from ipalib.plugins.user import NO_UPG_MAGIC if api.env.in_server and api.env.context in ['lite', 'server']: try: @@ -32,6 +30,7 @@ if api.env.in_server and api.env.context in ['lite', 'server']: except StandardError, e: raise e from ipalib import _ +from ipapython.dn import DN __doc__ = _(""" Migration to IPA @@ -114,18 +113,10 @@ _dn_err_msg = _('Malformed DN') _supported_schemas = (u'RFC2307bis', u'RFC2307') -_compat_dn = "cn=Schema Compatibility,cn=plugins,cn=config" - -def is_DN_syntax(ldap, attr): - """ - Check the schema to see if the attribute uses DN syntax. - - Returns True/False - """ - obj = ldap.schema.get_obj(_ldap.schema.AttributeType, attr) - return obj is not None and obj.syntax == '1.3.6.1.4.1.1466.115.121.1.12' +_compat_dn = DN(('cn', 'Schema Compatibility'), ('cn', 'plugins'), ('cn', 'config')) def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs): + assert isinstance(dn, DN) attr_blacklist = ['krbprincipalkey','memberofindirect','memberindirect'] attr_blacklist.extend(kwargs.get('attr_blacklist', [])) ds_ldap = ctx['ds_ldap'] @@ -198,17 +189,18 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs # tree for attr in entry_attrs.keys(): - if is_DN_syntax(ldap, attr): + if ldap.has_dn_syntax(attr): for ind, value in enumerate(entry_attrs[attr]): + assert isinstance(value, DN) try: (remote_dn, remote_entry) = ds_ldap.get_entry(value, [api.Object.user.primary_key.name, api.Object.group.primary_key.name]) except errors.NotFound: api.log.warn('%s: attribute %s refers to non-existent entry %s' % (pkey, attr, value)) continue - if value.lower().endswith(search_bases['user']): + if value.endswith(search_bases['user']): primary_key = api.Object.user.primary_key.name container = api.env.container_user - elif value.lower().endswith(search_bases['group']): + elif value.endswith(search_bases['group']): primary_key = api.Object.group.primary_key.name container = api.env.container_group else: @@ -221,15 +213,13 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs api.log.debug('converting DN value %s for %s in %s' % (value, attr, dn)) rdnval = remote_entry[primary_key][0].lower() - entry_attrs[attr][ind] = \ - str(DN((primary_key, rdnval), - container, - api.env.basedn)) + entry_attrs[attr][ind] = DN((primary_key, rdnval), container, api.env.basedn) return dn def _post_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx): + assert isinstance(dn, DN) # add user to the default group try: ldap.add_entry_to_group(dn, ctx['def_group_dn']) @@ -246,6 +236,7 @@ def _post_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx): # GROUP MIGRATION CALLBACKS AND VARS def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs): + def convert_members_rfc2307bis(member_attr, search_bases, overwrite=False): """ Convert DNs in member attributes to work in IPA. @@ -253,24 +244,19 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg new_members = [] entry_attrs.setdefault(member_attr, []) for m in entry_attrs[member_attr]: + assert isinstance(m, DN) try: - # what str2dn returns looks like [[('cn', 'foo', 4)], [('dc', 'example', 1)], [('dc', 'com', 1)]] - rdn = _ldap.dn.str2dn(m ,flags=_ldap.DN_FORMAT_LDAPV3)[0] - rdnval = rdn[0][1] + rdnval = m[0].value except IndexError: api.log.error('Malformed DN %s has no RDN?' % m) continue - if m.lower().endswith(search_bases['user']): + if m.endswith(search_bases['user']): api.log.info('migrating user %s' % m) - m = '%s=%s,%s' % (api.Object.user.primary_key.name, - rdnval, - api.env.container_user) - elif m.lower().endswith(search_bases['group']): + m = DN((api.Object.user.primary_key.name, rdnval), api.env.container_user) + elif m.endswith(search_bases['group']): api.log.info('migrating group %s' % m) - m = '%s=%s,%s' % (api.Object.group.primary_key.name, - rdnval, - api.env.container_group) + m = DN((api.Object.group.primary_key.name, rdnval), api.env.container_group) else: api.log.error('entry %s does not belong into any known container' % m) continue @@ -290,12 +276,11 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg new_members = [] entry_attrs.setdefault(member_attr, []) for m in entry_attrs[member_attr]: - memberdn = '%s=%s,%s' % (api.Object.user.primary_key.name, - m, - api.env.container_user) + memberdn = DN((api.Object.user.primary_key.name, m), api.env.container_user) new_members.append(ldap.normalize_dn(memberdn)) entry_attrs['member'] = new_members + assert isinstance(dn, DN) attr_blacklist = ['memberofindirect','memberindirect'] attr_blacklist.extend(kwargs.get('attr_blacklist', [])) @@ -330,6 +315,7 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg def _group_exc_callback(ldap, dn, entry_attrs, exc, options): + assert isinstance(dn, DN) if isinstance(exc, errors.DuplicateEntry): if options.get('groupoverwritegid', False) and \ entry_attrs.get('gidnumber') is not None: @@ -424,24 +410,24 @@ class migrate_ds(Command): ) takes_options = ( - Str('binddn?', validate_dn_param, + DNParam('binddn?', cli_name='bind_dn', label=_('Bind DN'), - default=u'cn=directory manager', + default=DN(('cn', 'directory manager')), autofill=True, ), - Str('usercontainer', validate_dn_param, + DNParam('usercontainer', cli_name='user_container', label=_('User container'), doc=_('DN of container for users in DS relative to base DN'), - default=u'ou=people', + default=DN(('ou', 'people')), autofill=True, ), - Str('groupcontainer', validate_dn_param, + DNParam('groupcontainer', cli_name='group_container', label=_('Group container'), doc=_('DN of container for groups in DS relative to base DN'), - default=u'ou=groups', + default=DN(('ou', 'groups')), autofill=True, ), Str('userobjectclass+', @@ -511,7 +497,7 @@ class migrate_ds(Command): doc=_('Continuous operation mode. Errors are reported but the process continues'), default=False, ), - Str('basedn?', + DNParam('basedn?', cli_name='base_dn', label=_('Base DN'), doc=_('Base DN on remote LDAP server'), @@ -594,11 +580,9 @@ can use their Kerberos accounts.''') def _get_search_bases(self, options, ds_base_dn, migrate_order): search_bases = dict() - ds_base_dn = DN(ds_base_dn) for ldap_obj_name in migrate_order: container = options.get('%scontainer' % to_cli(ldap_obj_name)) if container: - container = DN(container) # Don't append base dn if user already appended it in the container dn if container.endswith(ds_base_dn): search_base = container @@ -606,13 +590,14 @@ can use their Kerberos accounts.''') search_base = DN(container, ds_base_dn) else: search_base = ds_base_dn - search_bases[ldap_obj_name] = str(search_base) + search_bases[ldap_obj_name] = search_base return search_bases def migrate(self, ldap, config, ds_ldap, ds_base_dn, options): """ Migrate objects from DS to LDAP. """ + assert isinstance(ds_base_dn, DN) migrated = {} # {'OBJ': ['PKEY1', 'PKEY2', ...], ...} failed = {} # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...} search_bases = self._get_search_bases(options, ds_base_dn, self.migrate_order) @@ -703,6 +688,7 @@ can use their Kerberos accounts.''') continue dn = ldap_obj.get_dn(pkey) + assert isinstance(dn, DN) entry_attrs['objectclass'] = list( set( config.get( @@ -722,6 +708,7 @@ can use their Kerberos accounts.''') valid_gids = valid_gids, **blacklists ) + assert isinstance(dn, DN) if not dn: continue except errors.NotFound, e: @@ -760,6 +747,8 @@ can use their Kerberos accounts.''') config = ldap.get_ipa_config()[1] ds_base_dn = options.get('basedn') + if ds_base_dn is not None: + assert isinstance(ds_base_dn, DN) # check if migration mode is enabled if config.get('ipamigrationenabled', ('FALSE', ))[0] == 'FALSE': @@ -773,6 +762,7 @@ can use their Kerberos accounts.''') if not options.get('compat'): try: (dn,check_compat) = ldap.get_entry(_compat_dn, normalize=False) + assert isinstance(dn, DN) if check_compat is not None and \ check_compat.get('nsslapd-pluginenabled', [''])[0].lower() == 'on': return dict(result={}, failed={}, enabled=True, compat=False) @@ -782,14 +772,16 @@ can use their Kerberos accounts.''') if not ds_base_dn: # retrieve base DN from remote LDAP server (entries, truncated) = ds_ldap.find_entries( - '', ['namingcontexts', 'defaultnamingcontext'], '', + '', ['namingcontexts', 'defaultnamingcontext'], DN(''), _ldap.SCOPE_BASE, size_limit=-1, time_limit=0, ) if 'defaultnamingcontext' in entries[0][1]: - ds_base_dn = entries[0][1]['defaultnamingcontext'][0] + ds_base_dn = DN(entries[0][1]['defaultnamingcontext'][0]) + assert isinstance(ds_base_dn, DN) else: try: - ds_base_dn = entries[0][1]['namingcontexts'][0] + ds_base_dn = DN(entries[0][1]['namingcontexts'][0]) + assert isinstance(ds_base_dn, DN) except (IndexError, KeyError), e: raise StandardError(str(e)) diff --git a/ipalib/plugins/netgroup.py b/ipalib/plugins/netgroup.py index 4236feeb7..263d66b55 100644 --- a/ipalib/plugins/netgroup.py +++ b/ipalib/plugins/netgroup.py @@ -162,6 +162,7 @@ class netgroup_add(LDAPCreate): u'Hostgroups and netgroups share a common namespace') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) entry_attrs.setdefault('nisdomainname', self.api.env.domain) try: @@ -203,6 +204,7 @@ class netgroup_mod(LDAPUpdate): msg_summary = _('Modified netgroup "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, attrs_list) except errors.NotFound: @@ -238,6 +240,7 @@ class netgroup_find(LDAPSearch): ) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) # Do not display private mepManagedEntry netgroups by default # If looking for managed groups, we need to omit the negation search filter @@ -267,8 +270,11 @@ class netgroup_add_member(LDAPAddMember): member_attributes = ['memberuser', 'memberhost', 'member'] has_output_params = LDAPAddMember.has_output_params + output_params def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) return add_external_pre_callback('host', ldap, dn, keys, options) + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(netgroup_add_member) @@ -280,6 +286,7 @@ class netgroup_remove_member(LDAPRemoveMember): member_attributes = ['memberuser', 'memberhost', 'member'] has_output_params = LDAPRemoveMember.has_output_params + output_params def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(netgroup_remove_member) diff --git a/ipalib/plugins/passwd.py b/ipalib/plugins/passwd.py index 9bee314ec..2c83560b1 100644 --- a/ipalib/plugins/passwd.py +++ b/ipalib/plugins/passwd.py @@ -24,6 +24,7 @@ from ipalib import _ from ipalib import output from ipalib.plugins.user import split_principal, validate_principal, normalize_principal from ipalib.request import context +from ipapython.dn import DN __doc__ = _(""" Set a user's password @@ -104,7 +105,7 @@ class passwd(Command): (dn, entry_attrs) = ldap.find_entry_by_attr( 'krbprincipalname', principal, 'posixaccount', [''], - ",".join([api.env.container_user, api.env.basedn]) + DN(api.env.container_user, api.env.basedn) ) if principal == getattr(context, 'principal') and \ diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py index 89f9eaa62..befa74df8 100644 --- a/ipalib/plugins/permission.py +++ b/ipalib/plugins/permission.py @@ -22,6 +22,7 @@ from ipalib import api, _, ngettext from ipalib import Flag, Str, StrEnum from ipalib.request import context from ipalib import errors +from ipapython.dn import DN, EditableDN __doc__ = _(""" Permissions @@ -202,6 +203,7 @@ class permission_add(LDAPCreate): has_output_params = LDAPCreate.has_output_params + output_params def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # Test the ACI before going any further opts = self.obj.filter_aci_attributes(options) opts['test'] = True @@ -219,6 +221,7 @@ class permission_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) # Now actually add the aci. opts = self.obj.filter_aci_attributes(options) opts['test'] = False @@ -275,6 +278,7 @@ class permission_add_noaci(LDAPCreate): yield option def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) permission_type = options.get('permissiontype') if permission_type: entry_attrs['ipapermissiontype'] = [ permission_type ] @@ -297,6 +301,7 @@ class permission_del(LDAPDelete): ) def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) if not options.get('force') and not self.obj.check_system(ldap, dn, *keys): raise errors.ACIError(info='A SYSTEM permission may not be removed') # remove permission even when the underlying ACI is missing @@ -316,6 +321,7 @@ class permission_mod(LDAPUpdate): has_output_params = LDAPUpdate.has_output_params + output_params def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if not self.obj.check_system(ldap, dn, *keys): raise errors.ACIError(info='A SYSTEM permission may not be modified') @@ -332,10 +338,13 @@ class permission_mod(LDAPUpdate): if 'rename' in options: if options['rename']: try: - new_dn = dn.replace(keys[-1].lower(), options['rename'], 1) - (new_dn, attrs) = ldap.get_entry( - new_dn, attrs_list, normalize=self.obj.normalize_dn - ) + try: + new_dn = EditableDN(dn) + new_dn[0]['cn'] # assure the first RDN has cn as it's type + except (IndexError, KeyError), e: + raise ValueError("expected dn starting with 'cn=' but got '%s'" % dn) + new_dn[0].value = options['rename'] + (new_dn, attrs) = ldap.get_entry(new_dn, attrs_list, normalize=self.obj.normalize_dn) raise errors.DuplicateEntry() except errors.NotFound: pass # permission may be renamed, continue @@ -371,6 +380,7 @@ class permission_mod(LDAPUpdate): raise exc def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) # rename the underlying ACI after the change to permission cn = keys[-1] @@ -480,6 +490,7 @@ class permission_show(LDAPRetrieve): has_output_params = LDAPRetrieve.has_output_params + output_params def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) try: common_options = filter_options(options, ['all', 'raw']) aci = self.api.Command.aci_show(keys[-1], aciprefix=ACI_PREFIX, diff --git a/ipalib/plugins/pkinit.py b/ipalib/plugins/pkinit.py index cb3b9c2fc..2d11f0244 100644 --- a/ipalib/plugins/pkinit.py +++ b/ipalib/plugins/pkinit.py @@ -21,6 +21,7 @@ from ipalib import api, errors from ipalib import Int, Str from ipalib import Object, Command from ipalib import _ +from ipapython.dn import DN __doc__ = _(""" Kerberos pkinit options @@ -67,9 +68,7 @@ class pkinit_anonymous(Command): __doc__ = _('Enable or Disable Anonymous PKINIT.') princ_name = 'WELLKNOWN/ANONYMOUS@%s' % api.env.realm - default_dn = 'krbprincipalname=%s,cn=%s,cn=kerberos,%s' % ( - princ_name, api.env.realm, api.env.basedn - ) + default_dn = DN(('krbprincipalname', princ_name), ('cn', api.env.realm), ('cn', 'kerberos'), api.env.basedn) takes_args = ( Str('action', valid_arg), diff --git a/ipalib/plugins/pwpolicy.py b/ipalib/plugins/pwpolicy.py index 77e6f2c79..33c8329f7 100644 --- a/ipalib/plugins/pwpolicy.py +++ b/ipalib/plugins/pwpolicy.py @@ -19,11 +19,12 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from ipalib import api -from ipalib import Int, Str +from ipalib import Int, Str, DNParam from ipalib.plugins.baseldap import * from ipalib import _ from ipalib.request import context from ipapython.ipautil import run +from ipapython.dn import DN from distutils import version __doc__ = _(""" @@ -75,13 +76,13 @@ class cosentry(LDAPObject): """ NO_CLI = True - container_dn = 'cn=costemplates,%s' % api.env.container_accounts + container_dn = DN(('cn', 'costemplates'), api.env.container_accounts) object_class = ['top', 'costemplate', 'extensibleobject', 'krbcontainer'] default_attributes = ['cn', 'cospriority', 'krbpwdpolicyreference'] takes_params = ( Str('cn', primary_key=True), - Str('krbpwdpolicyreference'), + DNParam('krbpwdpolicyreference'), Int('cospriority', minvalue=0), ) @@ -102,8 +103,7 @@ class cosentry(LDAPObject): )['result'] if len(entries) > 0: group_name = self.api.Object.group.get_primary_key_from_dn( - entries[0]['cn'][0] - ) + DN(entries[0]['cn'][0])) raise errors.ValidationError( name='priority', error=self.priority_not_unique_msg % { @@ -119,6 +119,7 @@ class cosentry_add(LDAPCreate): NO_CLI = True def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # check for existence of the group result = self.api.Command.group_show(keys[-1], all=True)['result'] oc = map(lambda x:x.lower(),result['objectclass']) @@ -141,6 +142,7 @@ class cosentry_mod(LDAPUpdate): NO_CLI = True def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) new_cospriority = options.get('cospriority') if new_cospriority is not None: cos_entry = self.api.Command.cosentry_show(keys[-1])['result'] @@ -167,13 +169,13 @@ api.register(cosentry_find) global_policy_name = 'global_policy' -global_policy_dn = 'cn=%s,cn=%s,cn=kerberos,%s' % (global_policy_name, api.env.realm, api.env.basedn) +global_policy_dn = DN(('cn', global_policy_name), ('cn', api.env.realm), ('cn', 'kerberos'), api.env.basedn) class pwpolicy(LDAPObject): """ Password Policy object """ - container_dn = 'cn=%s,cn=kerberos' % api.env.realm + container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos')) object_name = _('password policy') object_name_plural = _('password policies') object_class = ['top', 'nscontainer', 'krbpwdpolicy'] @@ -339,6 +341,7 @@ class pwpolicy_add(LDAPCreate): yield self.obj.primary_key.clone(attribute=True, required=True) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) self.obj.convert_time_on_input(entry_attrs) self.obj.validate_lifetime(entry_attrs, True) self.api.Command.cosentry_add( @@ -348,6 +351,7 @@ class pwpolicy_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.log.info('%r' % entry_attrs) # attribute rights are not allowed for pwpolicy_add self.obj.add_cospriority(entry_attrs, keys[-1], rights=False) @@ -366,7 +370,8 @@ class pwpolicy_del(LDAPDelete): ) def pre_callback(self, ldap, dn, *keys, **options): - if dn.lower() == global_policy_dn.lower(): + assert isinstance(dn, DN) + if dn == global_policy_dn: raise errors.ValidationError( name='group', error=_('cannot delete global password policy') @@ -374,6 +379,7 @@ class pwpolicy_del(LDAPDelete): return dn def post_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) try: self.api.Command.cosentry_del(keys[-1]) except errors.NotFound: @@ -387,6 +393,7 @@ class pwpolicy_mod(LDAPUpdate): __doc__ = _('Modify a group password policy.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) self.obj.convert_time_on_input(entry_attrs) self.obj.validate_lifetime(entry_attrs, False, *keys) setattr(context, 'cosupdate', False) @@ -408,6 +415,7 @@ class pwpolicy_mod(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) rights = options.get('all', False) and options.get('rights', False) self.obj.add_cospriority(entry_attrs, keys[-1], rights) self.obj.convert_time_for_output(entry_attrs, **options) @@ -436,6 +444,7 @@ class pwpolicy_show(LDAPRetrieve): ) def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + assert isinstance(dn, DN) if options.get('user') is not None: user_entry = self.api.Command.user_show( options['user'], all=True @@ -445,6 +454,7 @@ class pwpolicy_show(LDAPRetrieve): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) rights = options.get('all', False) and options.get('rights', False) self.obj.add_cospriority(entry_attrs, keys[-1], rights) self.obj.convert_time_for_output(entry_attrs, **options) diff --git a/ipalib/plugins/range.py b/ipalib/plugins/range.py index 39849b661..c1d918679 100644 --- a/ipalib/plugins/range.py +++ b/ipalib/plugins/range.py @@ -96,6 +96,7 @@ class range_add(LDAPCreate): msg_summary = _('Added ID range "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if ('ipanttrusteddomainsid' not in options and 'ipasecondarybaserid' not in options): raise errors.ValidationError(name=_('Range setup'), @@ -110,6 +111,7 @@ class range_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.handle_iparangetype(entry_attrs, options, keep_objectclass=True) return dn @@ -128,6 +130,7 @@ class range_find(LDAPSearch): # Since all range types are stored within separate containers under # 'cn=ranges,cn=etc' search can be done on a one-level scope def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) attrs_list.append('objectclass') return (filters, base_dn, ldap.SCOPE_ONELEVEL) @@ -140,10 +143,12 @@ class range_show(LDAPRetrieve): __doc__ = _('Display information about a range.') def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + assert isinstance(dn, DN) attrs_list.append('objectclass') return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.handle_iparangetype(entry_attrs, options) return dn @@ -153,10 +158,12 @@ class range_mod(LDAPUpdate): msg_summary = _('Modified ID range "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) attrs_list.append('objectclass') return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.handle_iparangetype(entry_attrs, options) return dn @@ -166,4 +173,3 @@ api.register(range_mod) api.register(range_del) api.register(range_find) api.register(range_show) - diff --git a/ipalib/plugins/selinuxusermap.py b/ipalib/plugins/selinuxusermap.py index 160e68c96..988cb4f0b 100644 --- a/ipalib/plugins/selinuxusermap.py +++ b/ipalib/plugins/selinuxusermap.py @@ -234,6 +234,7 @@ class selinuxusermap_add(LDAPCreate): msg_summary = _('Added SELinux User Map "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) # rules are enabled by default entry_attrs['ipaenabledflag'] = 'TRUE' validate_selinuxuser_inlist(ldap, entry_attrs['ipaselinuxuser']) @@ -243,6 +244,7 @@ class selinuxusermap_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj._convert_seealso(ldap, entry_attrs, **options) return dn @@ -264,6 +266,7 @@ class selinuxusermap_mod(LDAPUpdate): msg_summary = _('Modified SELinux User Map "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) try: (_dn, _entry_attrs) = ldap.get_entry(dn, attrs_list) except errors.NotFound: @@ -288,6 +291,7 @@ class selinuxusermap_mod(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj._convert_seealso(ldap, entry_attrs, **options) return dn @@ -331,6 +335,7 @@ class selinuxusermap_show(LDAPRetrieve): __doc__ = _('Display the properties of a SELinux User Map rule.') def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj._convert_seealso(ldap, entry_attrs, **options) return dn @@ -398,6 +403,7 @@ class selinuxusermap_add_user(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -428,6 +434,7 @@ class selinuxusermap_add_host(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py index 7cb7b8030..213711ab3 100644 --- a/ipalib/plugins/service.py +++ b/ipalib/plugins/service.py @@ -278,6 +278,7 @@ class service_add(LDAPCreate): ), ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) (service, hostname, realm) = split_principal(keys[-1]) if service.lower() == 'host' and not options['force']: raise errors.HostService() @@ -322,6 +323,7 @@ class service_del(LDAPDelete): msg_summary = _('Deleted service "%(value)s"') member_attributes = ['managedby'] def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) # In the case of services we don't want IPA master services to be # deleted. This is a limited few though. If the user has their own # custom services allow them to manage them. @@ -367,6 +369,7 @@ class service_mod(LDAPUpdate): member_attributes = ['managedby'] def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'usercertificate' in options: (service, hostname, realm) = split_principal(keys[-1]) cert = options.get('usercertificate') @@ -386,7 +389,9 @@ class service_mod(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) set_certificate_attrs(entry_attrs) + return dn api.register(service_mod) @@ -402,6 +407,7 @@ class service_find(LDAPSearch): 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))' \ @@ -439,6 +445,7 @@ class service_show(LDAPRetrieve): has_output_params = LDAPRetrieve.has_output_params + output_params def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) self.obj.get_password_attributes(ldap, dn, entry_attrs) set_certificate_attrs(entry_attrs) diff --git a/ipalib/plugins/sudorule.py b/ipalib/plugins/sudorule.py index 723cce2e4..e2937949b 100644 --- a/ipalib/plugins/sudorule.py +++ b/ipalib/plugins/sudorule.py @@ -246,6 +246,7 @@ class sudorule_add(LDAPCreate): __doc__ = _('Create new Sudo Rule.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) self.obj.check_order_uniqueness(*keys, **options) # Sudo Rules are enabled by default entry_attrs['ipaenabledflag'] = 'TRUE' @@ -269,6 +270,7 @@ class sudorule_mod(LDAPUpdate): msg_summary = _('Modified Sudo Rule "%(value)s"') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if 'sudoorder' in options: new_order = options.get('sudoorder') old_entry = self.api.Command.sudorule_show(keys[-1])['result'] @@ -371,6 +373,7 @@ class sudorule_add_allow_command(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -399,6 +402,7 @@ class sudorule_add_deny_command(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -426,6 +430,7 @@ class sudorule_add_user(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -435,6 +440,7 @@ class sudorule_add_user(LDAPAddMember): return add_external_pre_callback('user', ldap, dn, keys, options) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('memberuser', 'user', 'externaluser', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_add_user) @@ -447,6 +453,7 @@ class sudorule_remove_user(LDAPRemoveMember): member_count_out = ('%i object removed.', '%i objects removed.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('memberuser', 'user', 'externaluser', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_remove_user) @@ -459,6 +466,7 @@ class sudorule_add_host(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + assert isinstance(dn, DN) try: (_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes) except errors.NotFound: @@ -468,6 +476,7 @@ class sudorule_add_host(LDAPAddMember): return add_external_pre_callback('host', ldap, dn, keys, options) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_add_host) @@ -480,6 +489,7 @@ class sudorule_remove_host(LDAPRemoveMember): member_count_out = ('%i object removed.', '%i objects removed.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_remove_host) @@ -491,6 +501,7 @@ class sudorule_add_runasuser(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) def check_validity(runas): v = unicode(runas) if v.upper() == u'ALL': @@ -521,6 +532,7 @@ class sudorule_add_runasuser(LDAPAddMember): return add_external_pre_callback('user', ldap, dn, keys, options) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('ipasudorunas', 'user', 'ipasudorunasextuser', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_add_runasuser) @@ -533,6 +545,7 @@ class sudorule_remove_runasuser(LDAPRemoveMember): member_count_out = ('%i object removed.', '%i objects removed.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('ipasudorunas', 'user', 'ipasudorunasextuser', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_remove_runasuser) @@ -545,6 +558,7 @@ class sudorule_add_runasgroup(LDAPAddMember): member_count_out = ('%i object added.', '%i objects added.') def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) def check_validity(runas): v = unicode(runas) if v.upper() == u'ALL': @@ -569,6 +583,7 @@ class sudorule_add_runasgroup(LDAPAddMember): return add_external_pre_callback('group', ldap, dn, keys, options) def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return add_external_post_callback('ipasudorunasgroup', 'group', 'ipasudorunasextgroup', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_add_runasgroup) @@ -581,6 +596,7 @@ class sudorule_remove_runasgroup(LDAPRemoveMember): member_count_out = ('%i object removed.', '%i objects removed.') def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) return remove_external_post_callback('ipasudorunasgroup', 'group', 'ipasudorunasextgroup', ldap, completed, failed, dn, entry_attrs, keys, options) api.register(sudorule_remove_runasgroup) diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py index acb65b388..a70293bff 100644 --- a/ipalib/plugins/trust.py +++ b/ipalib/plugins/trust.py @@ -107,9 +107,10 @@ class trust(LDAPObject): ) def make_trust_dn(env, trust_type, dn): + assert isinstance(dn, DN) if trust_type in trust.trust_types: container_dn = DN(('cn', trust_type), env.container_trusts, env.basedn) - return unicode(DN(DN(dn)[0], container_dn)) + return DN(dn[0], container_dn) return dn class trust_add(LDAPCreate): @@ -214,6 +215,7 @@ class trust_del(LDAPDelete): msg_summary = _('Deleted trust "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) try: result = self.api.Command.trust_show(keys[-1]) except errors.NotFound, e: @@ -226,6 +228,7 @@ class trust_mod(LDAPUpdate): msg_summary = _('Modified trust "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) result = None try: result = self.api.Command.trust_show(keys[-1]) @@ -245,6 +248,7 @@ class trust_find(LDAPSearch): # Since all trusts types are stored within separate containers under 'cn=trusts', # search needs to be done on a sub-tree scope def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options): + assert isinstance(base_dn, DN) return (filters, base_dn, ldap.SCOPE_SUBTREE) class trust_show(LDAPRetrieve): @@ -271,6 +275,7 @@ class trust_show(LDAPRetrieve): return result def pre_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if 'trust_show_type' in options: return make_trust_dn(self.env, options['trust_show_type'], dn) return dn @@ -281,4 +286,3 @@ api.register(trust_mod) api.register(trust_del) api.register(trust_find) api.register(trust_show) - diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py index c19d9a666..529699f9a 100644 --- a/ipalib/plugins/user.py +++ b/ipalib/plugins/user.py @@ -375,11 +375,12 @@ class user(LDAPObject): if not manager: return None - if isinstance(manager, basestring): + if not isinstance(manager, list): manager = [manager] try: + container_dn = DN(self.container_dn, api.env.basedn) for m in xrange(len(manager)): - if manager[m].endswith('%s,%s' % (self.container_dn, api.env.basedn)): + if isinstance(manager[m], DN) and manager[m].endswith(container_dn): continue (dn, entry_attrs) = self.backend.find_entry_by_attr( self.primary_key.name, manager[m], self.object_class, [''], @@ -420,6 +421,7 @@ class user_add(LDAPCreate): ) def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if not options.get('noprivate', False): try: # The Managed Entries plugin will allow a user to be created @@ -459,7 +461,9 @@ class user_add(LDAPCreate): homes_root = config.get('ipahomesrootdir', ['/home'])[0] # build user's home directory based on his uid entry_attrs['homedirectory'] = posixpath.join(homes_root, keys[-1]) - entry_attrs.setdefault('krbpwdpolicyreference', 'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)) + entry_attrs.setdefault('krbpwdpolicyreference', + DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'), + api.env.basedn)) entry_attrs.setdefault('krbprincipalname', '%s@%s' % (entry_attrs['uid'], api.env.realm)) if entry_attrs.get('gidnumber', DNA_MAGIC) == DNA_MAGIC: @@ -496,6 +500,7 @@ class user_add(LDAPCreate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) config = ldap.get_ipa_config()[1] # add the user we just created into the default primary group def_primary_group = config.get('ipadefaultprimarygroup') @@ -544,6 +549,7 @@ class user_del(LDAPDelete): msg_summary = _('Deleted user "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): + assert isinstance(dn, DN) protected_group_name = u'admins' result = api.Command.group_show(protected_group_name) if result['result'].get('member_user', []) == [keys[-1]]: @@ -562,6 +568,7 @@ class user_mod(LDAPUpdate): has_output_params = LDAPUpdate.has_output_params + user_output_params def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) if options.get('rename') is not None: config = ldap.get_ipa_config()[1] if 'ipamaxusernamelength' in config: @@ -592,6 +599,7 @@ class user_mod(LDAPUpdate): return dn def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) if options.get('random', False): try: entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword')) @@ -621,6 +629,7 @@ class user_find(LDAPSearch): ) def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options): + assert isinstance(base_dn, DN) if options.get('whoami'): return ("(&(objectclass=posixaccount)(krbprincipalname=%s))"%\ getattr(context, 'principal'), base_dn, scope) @@ -651,6 +660,7 @@ class user_show(LDAPRetrieve): has_output_params = LDAPRetrieve.has_output_params + user_output_params def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) convert_nsaccountlock(entry_attrs) self.obj._convert_manager(entry_attrs, **options) self.obj.get_password_attributes(ldap, dn, entry_attrs) @@ -763,7 +773,7 @@ class user_status(LDAPQuery): # Get list of masters try: (masters, truncated) = ldap.find_entries( - None, ['*'], 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn, + None, ['*'], DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn), ldap.SCOPE_ONELEVEL ) except errors.NotFound: diff --git a/ipalib/plugins/virtual.py b/ipalib/plugins/virtual.py index c827d3d9d..8db1a9653 100644 --- a/ipalib/plugins/virtual.py +++ b/ipalib/plugins/virtual.py @@ -23,6 +23,7 @@ Base classes for non-LDAP backend plugins. from ipalib import api from ipalib import Command from ipalib import errors +from ipapython.dn import DN class VirtualCommand(Command): """ @@ -55,7 +56,7 @@ class VirtualCommand(Command): ldap = self.api.Backend.ldap2 self.log.debug("IPA: virtual verify %s" % operation) - operationdn = "cn=%s,%s,%s" % (operation, self.api.env.container_virtual, self.api.env.basedn) + operationdn = DN(('cn', operation), self.api.env.container_virtual, self.api.env.basedn) try: if not ldap.can_write(operationdn, "objectclass"): |