From 65a146cdca7c62301b5be978027a44d880424529 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Fri, 21 Jan 2011 09:20:01 +0100 Subject: ACI plugin supports prefixes When more than one plugin produce ACIs, they share common namespace of ACI name. This may lead to name collisions between the ACIs from different plugins. This patch introduces a mandatory "prefix" attribute for non-find ACI operations which allow plugins to use their own prefixes (i.e. namespaces) which is then used when a name of the ACI is generated. Permission, Delegation and Selfservice plugins has been updated to use their own prefixes thus avoiding name collisions by using their own namespaces. Default ACIs in LDIFs has been updated to follow this new policy. Permission plugin now uses its CN (=primary key) instead of description in ACI names as Description may not be unique. This change requires an IPA server reinstall since the default ACI set has been changed. https://fedorahosted.org/freeipa/ticket/764 --- ipalib/plugins/permission.py | 55 ++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 22 deletions(-) (limited to 'ipalib/plugins/permission.py') diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py index 14d7b9656..0c2855ff5 100644 --- a/ipalib/plugins/permission.py +++ b/ipalib/plugins/permission.py @@ -61,7 +61,7 @@ EXAMPLES: ipa permission-add --desc="Add a User" --type=user --permissions=add adduser Add a permission that grants the ability to manage group membership: - ipa permission-add --desc='Manage group members' --attrs=member --permissions=-write --type=group manage_group_members + ipa permission-add --desc='Manage group members' --attrs=member --permissions=write --type=group manage_group_members """ import copy @@ -70,6 +70,7 @@ from ipalib import api, _, ngettext from ipalib import Flag, Str, StrEnum from ipalib.request import context +ACI_PREFIX=u"permission" class permission(LDAPObject): """ @@ -167,8 +168,9 @@ class permission_add(LDAPCreate): del opts['description'] opts['test'] = True opts['permission'] = keys[-1] + opts['aciprefix'] = ACI_PREFIX try: - self.api.Command.aci_add(options['description'], **opts) + self.api.Command.aci_add(keys[-1], **opts) except Exception, e: raise e @@ -187,8 +189,9 @@ class permission_add(LDAPCreate): del opts['description'] opts['test'] = False opts['permission'] = keys[-1] + opts['aciprefix'] = ACI_PREFIX try: - result = self.api.Command.aci_add(options['description'], **opts)['result'] + result = self.api.Command.aci_add(keys[-1], **opts)['result'] for attr in self.obj.aci_attributes: if attr in result: entry_attrs[attr] = result[attr] @@ -204,7 +207,7 @@ class permission_add(LDAPCreate): except Exception, ignore: pass try: - self.api.Command.aci_del(keys[-1]) + self.api.Command.aci_del(keys[-1], aciprefix=ACI_PREFIX) except Exception, ignore: pass raise e @@ -221,12 +224,11 @@ class permission_del(LDAPDelete): msg_summary = _('Deleted permission "%(value)s"') def pre_callback(self, ldap, dn, *keys, **options): - (dn, entry_attrs) = ldap.get_entry(dn, ['*']) - if 'description' in entry_attrs: - try: - self.api.Command.aci_del(entry_attrs['description'][0]) - except errors.NotFound: - pass + # remove permission even when the underlying ACI is missing + try: + self.api.Command.aci_del(keys[-1], aciprefix=ACI_PREFIX) + except errors.NotFound: + pass return dn api.register(permission_del) @@ -247,9 +249,7 @@ class permission_mod(LDAPUpdate): except errors.NotFound: self.obj.handle_not_found(*keys) opts = copy.copy(options) - if 'description' in opts: - del opts['description'] - for o in ['all', 'raw', 'rights', 'description']: + for o in ['all', 'raw', 'rights', 'description', 'rename']: if o in opts: del opts[o] setattr(context, 'aciupdate', False) @@ -258,8 +258,9 @@ class permission_mod(LDAPUpdate): if len(opts) > 0: opts['test'] = False opts['permission'] = keys[-1] + opts['aciprefix'] = ACI_PREFIX try: - self.api.Command.aci_mod(attrs['description'][0], **opts) + self.api.Command.aci_mod(keys[-1], **opts) setattr(context, 'aciupdate', True) except Exception, e: raise e @@ -271,10 +272,6 @@ class permission_mod(LDAPUpdate): except: pass - if 'description' in options: - if attrs['description'][0] != options['description']: - self.api.Command.aci_rename(attrs['description'][0], newname=options['description']) - return dn def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs): @@ -294,6 +291,15 @@ class permission_mod(LDAPUpdate): raise exc def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + # rename the underlying ACI after the change to permission + if 'rename' in options: + aciname = keys[-1] # ACI still refers to the old permission CN + self.api.Command.aci_mod(aciname,aciprefix=ACI_PREFIX, + permission=options['rename']) + + self.api.Command.aci_rename(aciname, aciprefix=ACI_PREFIX, + newname=keys[-1], newprefix=ACI_PREFIX) + result = self.api.Command.permission_show(keys[-1])['result'] for r in result: if not r.startswith('member'): @@ -317,24 +323,29 @@ class permission_find(LDAPSearch): for entry in entries: (dn, attrs) = entry try: - aci = self.api.Command.aci_show(attrs['description'][0])['result'] + aci = self.api.Command.aci_show(attrs['cn'][0], aciprefix=ACI_PREFIX)['result'] + + # copy information from respective ACI to permission entry for attr in self.obj.aci_attributes: if attr in aci: attrs[attr] = aci[attr] except errors.NotFound: - self.debug('ACI not found for %s' % attrs['description'][0]) + self.debug('ACI not found for %s' % attrs['cn'][0]) # Now find all the ACIs that match. Once we find them, add any that # aren't already in the list along with their permission info. + options['aciprefix'] = ACI_PREFIX + aciresults = self.api.Command.aci_find(*args, **options) truncated = truncated or aciresults['truncated'] results = aciresults['result'] + for aci in results: found = False if 'permission' in aci: for entry in entries: (dn, attrs) = entry - if aci['permission'] == attrs['cn']: + if aci['permission'] == attrs['cn'][0]: found = True break if not found: @@ -359,7 +370,7 @@ class permission_show(LDAPRetrieve): """ def post_callback(self, ldap, dn, entry_attrs, *keys, **options): try: - aci = self.api.Command.aci_show(entry_attrs['description'][0])['result'] + aci = self.api.Command.aci_show(keys[-1], aciprefix=ACI_PREFIX)['result'] for attr in self.obj.aci_attributes: if attr in aci: entry_attrs[attr] = aci[attr] -- cgit