summaryrefslogtreecommitdiffstats
path: root/ipalib/plugins/permission.py
diff options
context:
space:
mode:
authorPetr Viktorin <pviktori@redhat.com>2014-03-04 16:59:33 +0100
committerMartin Kosek <mkosek@redhat.com>2014-03-14 10:14:05 +0100
commitf58ffe176c57d01274888638d637b230c1081a60 (patch)
tree92d4350964ce9e949359b37aa7dbbef5c5284ed1 /ipalib/plugins/permission.py
parent3120a6833e71d28fb0dcbbd62190b5f9c2e2c466 (diff)
downloadfreeipa-f58ffe176c57d01274888638d637b230c1081a60.tar.gz
freeipa-f58ffe176c57d01274888638d637b230c1081a60.tar.xz
freeipa-f58ffe176c57d01274888638d637b230c1081a60.zip
permission plugin: Write support for extratargetfilter
Extend the permission-add and permission-mod commands to process extratargetfilter. Part of the work for: https://fedorahosted.org/freeipa/ticket/4216 Reviewed-By: Martin Kosek <mkosek@redhat.com>
Diffstat (limited to 'ipalib/plugins/permission.py')
-rw-r--r--ipalib/plugins/permission.py135
1 files changed, 88 insertions, 47 deletions
diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py
index d8eeea28b..7dde36d62 100644
--- a/ipalib/plugins/permission.py
+++ b/ipalib/plugins/permission.py
@@ -285,6 +285,61 @@ class permission(baseldap.LDAPObject):
raise errors.ACIError(
info=_('A SYSTEM permission may not be modified or removed'))
+ def _get_filter_attr_info(self, entry):
+ """Get information on filter-related virtual attributes
+
+ Returns a dict with this information:
+ 'implicit_targetfilters': targetfilters implied by memberof and type
+ 'memberof': list of names of groups from memberof
+ 'type': the type
+ """
+ ipapermtargetfilter = entry.get('ipapermtargetfilter', [])
+ ipapermlocation = entry.single_value.get('ipapermlocation')
+
+ implicit_targetfilters = set()
+ result = {'implicit_targetfilters': implicit_targetfilters}
+
+ # memberof
+ memberof = []
+ for targetfilter in ipapermtargetfilter:
+ match = re.match('^\(memberof=(.*)\)$', targetfilter, re.I)
+ if match:
+ dn = DN(match.group(1))
+ groups_dn = DN(self.api.Object.group.container_dn,
+ self.api.env.basedn)
+ if dn[1:] == groups_dn[:] and dn[0].attr == 'cn':
+ memberof.append(dn[0].value)
+ implicit_targetfilters.add(match.group(0))
+ if memberof:
+ result['memberof'] = memberof
+
+ # type
+ if ipapermtargetfilter and ipapermlocation:
+ for obj in self.api.Object():
+ filter_objectclasses = getattr(
+ obj, 'permission_filter_objectclasses', None)
+ if not filter_objectclasses:
+ continue
+ wantdn = DN(obj.container_dn, self.api.env.basedn)
+ if DN(ipapermlocation) != wantdn:
+ continue
+
+ objectclass_targetfilters = set()
+ for objclass in filter_objectclasses:
+ filter_re = '\(objectclass=%s\)' % re.escape(objclass)
+ for tf in ipapermtargetfilter:
+ if re.match(filter_re, tf, re.I):
+ objectclass_targetfilters.add(tf)
+ break
+ else:
+ break
+ else:
+ result['type'] = [unicode(obj.name)]
+ implicit_targetfilters |= objectclass_targetfilters
+ break
+
+ return result
+
def postprocess_result(self, entry, options):
"""Update a permission entry for output (in place)
@@ -299,23 +354,6 @@ class permission(baseldap.LDAPObject):
if not options.get('raw') and not options.get('pkey_only'):
ipapermtargetfilter = entry.get('ipapermtargetfilter', [])
ipapermtarget = entry.single_value.get('ipapermtarget')
- ipapermlocation = entry.single_value.get('ipapermlocation')
-
- implicit_targetfilters = set()
-
- # memberof
- memberof = []
- for targetfilter in ipapermtargetfilter:
- match = re.match('^\(memberof=(.*)\)$', targetfilter, re.I)
- if match:
- dn = DN(match.group(1))
- groups_dn = DN(self.api.Object.group.container_dn,
- self.api.env.basedn)
- if dn[1:] == groups_dn[:] and dn[0].attr == 'cn':
- memberof.append(dn[0].value)
- implicit_targetfilters.add(match.group(0))
- if memberof:
- entry['memberof'] = memberof
# targetgroup
if ipapermtarget:
@@ -325,34 +363,15 @@ class permission(baseldap.LDAPObject):
dn[0].attr == 'cn' and dn[0].value != '*'):
entry.single_value['targetgroup'] = dn[0].value
- # type
- if ipapermtargetfilter and ipapermlocation:
- for obj in self.api.Object():
- filter_objectclasses = getattr(
- obj, 'permission_filter_objectclasses', None)
- if not filter_objectclasses:
- continue
- wantdn = DN(obj.container_dn, self.api.env.basedn)
- if DN(ipapermlocation) != wantdn:
- continue
-
- objectclass_targetfilters = set()
- for objclass in filter_objectclasses:
- filter_re = '\(objectclass=%s\)' % re.escape(objclass)
- for tf in ipapermtargetfilter:
- if re.match(filter_re, tf, re.I):
- objectclass_targetfilters.add(tf)
- break
- else:
- break
- else:
- entry.single_value['type'] = unicode(obj.name)
- implicit_targetfilters |= objectclass_targetfilters
- break
-
- if ipapermtargetfilter:
+ filter_attr_info = self._get_filter_attr_info(entry)
+ if 'type' in filter_attr_info:
+ entry['type'] = filter_attr_info['type']
+ if 'memberof' in filter_attr_info:
+ entry['memberof'] = filter_attr_info['memberof']
+ if 'implicit_targetfilters' in filter_attr_info:
extratargetfilter = sorted(
- set(ipapermtargetfilter) - implicit_targetfilters)
+ set(ipapermtargetfilter) -
+ filter_attr_info['implicit_targetfilters'])
if extratargetfilter:
entry['extratargetfilter'] = extratargetfilter
@@ -652,7 +671,9 @@ class permission(baseldap.LDAPObject):
raise ValueError('Cannot convert ACI, %r != %r' % (new_acistring,
acistring))
- def preprocess_options(self, options, return_filter_ops=False):
+ def preprocess_options(self, options,
+ return_filter_ops=False,
+ merge_targetfilter=False):
"""Preprocess options (in-place)
:param options: A dictionary of options
@@ -667,8 +688,19 @@ class permission(baseldap.LDAPObject):
- remove: list of regular expression objects; values that match
any of them sould be removed
- add: list of values to be added, after any removals
+ :merge_targetfilter:
+ If true, the extratargetfilter is copied into ipapermtargetfilter.
"""
+ if 'extratargetfilter' in options:
+ if 'ipapermtargetfilter' in options:
+ raise errors.ValidationError(
+ name='ipapermtargetfilter',
+ error=_('cannot specify full target filter '
+ 'and extra target filter simultaneously'))
+ if merge_targetfilter:
+ options['ipapermtargetfilter'] = options['extratargetfilter']
+
filter_ops = {'add': [], 'remove': []}
if options.get('subtree'):
@@ -836,7 +868,7 @@ class permission_add(baseldap.LDAPCreate):
# Need to override execute so that processed options apply to
# the whole command, not just the callbacks
def execute(self, *keys, **options):
- self.obj.preprocess_options(options)
+ self.obj.preprocess_options(options, merge_targetfilter=True)
return super(permission_add, self).execute(*keys, **options)
def pre_callback(self, ldap, dn, entry, attrs_list, *keys, **options):
@@ -950,7 +982,8 @@ class permission_mod(baseldap.LDAPUpdate):
error=_('cannot rename managed permissions'))
option = self.options[option_name]
allow_mod = 'allow_mod_for_managed_permission' in option.flags
- if option.attribute and not allow_mod:
+ if (option.attribute and not allow_mod or
+ option_name == 'extratargetfilter'):
raise errors.ValidationError(
name=option_name,
error=_('not modifiable on managed permissions'))
@@ -994,6 +1027,14 @@ class permission_mod(baseldap.LDAPUpdate):
key not in self.obj.attribute_members):
entry.setdefault(key, value)
+ # For extratargetfilter, add it to the implicit filters
+ # to get the full target filter
+ if 'extratargetfilter' in options:
+ filter_attr_info = self.obj._get_filter_attr_info(entry)
+ entry['ipapermtargetfilter'] = (
+ list(options['extratargetfilter'] or []) +
+ list(filter_attr_info['implicit_targetfilters']))
+
filter_ops = context.filter_ops
removes = filter_ops.get('remove', [])
new_filters = set(