My patch 0580 was wrong; non-POSIX groups obviously lack the posixgroup objectclass. Actually the only objectclasses that all groups share are top and ipaobject.

This makes permission plugin & updater join multiple permission_filter_objectclasses filters with OR, and changes the --type group filter to (|(objectclass=ipausergroup)(objectclass=posixgroup)).

The first patch has some unrelated test fixes.


--
PetrĀ³

From 4555ed124fc24ad4c84e74795de170c0a0f4eb57 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 19 Jun 2014 19:06:19 +0200
Subject: [PATCH] Test and docstring fixes

The recent conversions to managed permissions left behind a few
failing tests. Fix them.

Also fix a now incorrect docstring in ipalib.config.
---
 ipalib/config.py                                   |  6 +-----
 ipatests/test_xmlrpc/test_old_permission_plugin.py | 14 ++++++++------
 ipatests/test_xmlrpc/test_permission_plugin.py     | 14 ++++++++------
 ipatests/test_xmlrpc/test_realmdomains_plugin.py   |  2 +-
 4 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/ipalib/config.py b/ipalib/config.py
index b12cfd32184edf964353fda9304dbb5149eb525f..e8958205dbe12e1bae1ac24351d46901a536f3e7 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -105,15 +105,11 @@ class Env(object):
     u'false'
 
     If an ``str`` value looks like an integer, it's automatically converted to
-    the ``int`` type.  Likewise, if an ``str`` value looks like a floating-point
-    number, it's automatically converted to the ``float`` type.  For example:
+    the ``int`` type.
 
     >>> env.lucky = '7'
     >>> env.lucky
     7
-    >>> env.three_halves = '1.5'
-    >>> env.three_halves
-    1.5
 
     Leading and trailing white-space is automatically stripped from ``str``
     values.  For example:
diff --git a/ipatests/test_xmlrpc/test_old_permission_plugin.py b/ipatests/test_xmlrpc/test_old_permission_plugin.py
index 9de397d67979bf54f808b0b61628ee444087af4b..e69c4f824981d5d0f7b3beecdbc5df098e764b3b 100644
--- a/ipatests/test_xmlrpc/test_old_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_old_permission_plugin.py
@@ -466,9 +466,9 @@ class test_old_permission(Declarative):
                 summary=u'2 permissions matched',
                 result=[
                     {
-                        'dn': DN(('cn','Modify Group Password Policy'),
+                        'dn': DN(('cn', 'System: Modify Group Password Policy'),
                                  api.env.container_permission, api.env.basedn),
-                        'cn': [u'Modify Group Password Policy'],
+                        'cn': [u'System: Modify Group Password Policy'],
                     },
                     {
                         'dn': DN(('cn', 'System: Read Group Password Policy'),
@@ -796,10 +796,10 @@ class test_old_permission(Declarative):
                 summary=u'1 permission matched',
                 result=[
                     {
-                        'dn': DN(('cn','Add user to default group'),
+                        'dn': DN(('cn', 'System: Add User to default group'),
                                  api.env.container_permission, api.env.basedn),
-                        'cn': [u'Add user to default group'],
-                        'objectclass': objectclasses.system_permission,
+                        'cn': [u'System: Add User to default group'],
+                        'objectclass': objectclasses.permission,
                         'member_privilege': [u'User Administrators'],
                         'attrs': [u'member'],
                         'targetgroup': u'ipausers',
@@ -807,7 +807,9 @@ class test_old_permission(Declarative):
                         'permissions': [u'write'],
                         'ipapermbindruletype': [u'permission'],
                         'ipapermtarget': [DN('cn=ipausers', groups_dn)],
-                        'subtree': u'ldap:///%s' % api.env.basedn,
+                        'subtree': u'ldap:///%s' % groups_dn,
+                        'ipapermdefaultattr': [u'member'],
+                        'ipapermissiontype': [u'V2', u'MANAGED', u'SYSTEM'],
                     }
                 ],
             ),
diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py
index a37876bea5c2d666548f7efa94f32ddbf044c0b4..feffc2eb1285d173d63a07bb42df8e64f816b618 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -758,9 +758,9 @@ class test_permission(Declarative):
                 summary=u'2 permissions matched',
                 result=[
                     {
-                        'dn': DN(('cn','Modify Group Password Policy'),
+                        'dn': DN(('cn', 'System: Modify Group Password Policy'),
                                  api.env.container_permission, api.env.basedn),
-                        'cn': [u'Modify Group Password Policy'],
+                        'cn': [u'System: Modify Group Password Policy'],
                     },
                     {
                         'dn': DN(('cn', 'System: Read Group Password Policy'),
@@ -1193,10 +1193,10 @@ class test_permission(Declarative):
                 summary=u'1 permission matched',
                 result=[
                     {
-                        'dn': DN(('cn','Add user to default group'),
+                        'dn': DN(('cn', 'System: Add User to default group'),
                                  api.env.container_permission, api.env.basedn),
-                        'cn': [u'Add user to default group'],
-                        'objectclass': objectclasses.system_permission,
+                        'cn': [u'System: Add User to default group'],
+                        'objectclass': objectclasses.permission,
                         'member_privilege': [u'User Administrators'],
                         'attrs': [u'member'],
                         'targetgroup': [u'ipausers'],
@@ -1206,7 +1206,9 @@ class test_permission(Declarative):
                         'ipapermtarget': [DN(
                             'cn=ipausers', api.env.container_group,
                             api.env.basedn)],
-                        'ipapermlocation': [api.env.basedn],
+                        'ipapermlocation': [groups_dn],
+                        'ipapermdefaultattr': [u'member'],
+                        'ipapermissiontype': [u'V2', u'MANAGED', u'SYSTEM'],
                     }
                 ],
             ),
diff --git a/ipatests/test_xmlrpc/test_realmdomains_plugin.py b/ipatests/test_xmlrpc/test_realmdomains_plugin.py
index a47fd6b98ed0aed012a49d6f2f6b016e350ef60c..ee8057d1d9aff004e9ed144577e4aed34dc7b8dc 100644
--- a/ipatests/test_xmlrpc/test_realmdomains_plugin.py
+++ b/ipatests/test_xmlrpc/test_realmdomains_plugin.py
@@ -70,7 +70,7 @@ class test_realmdomains(Declarative):
                         u'(targetfilter = "(objectclass=domainrelatedobject)")'
                         u'(version 3.0;acl '
                             u'"permission:System: Read Realm Domains";'
-                            u'allow (read,compare,search) '
+                            u'allow (compare,read,search) '
                             u'userdn = "ldap:///all";;)'
                     ],
                 ),
-- 
1.9.3

From 9a21b82e07218bff23861185a291298a745ba627 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 19 Jun 2014 18:14:31 +0200
Subject: [PATCH] permission plugin: Join --type objectclass filters with OR

For groups, we will need to filter on either posixgroup (which UPGs
have but non-posix groups don't) and groupofnames/nestedgroup
(which normal groups have but UPGs don't).
Join permission_filter_objectclasses with `|` and add them as
a single ipapermtargetfilter value.

Part of the work for: https://fedorahosted.org/freeipa/ticket/3566
---
 ipalib/plugins/permission.py                       | 40 +++++++++++++---------
 .../install/plugins/update_managed_permissions.py  |  5 +--
 2 files changed, 26 insertions(+), 19 deletions(-)

diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py
index 3c2127fcc03d2d711ae6e2bfd10407085b7c7c2b..52ab09b14de363e7b34a710ea6af81fac444b5c5 100644
--- a/ipalib/plugins/permission.py
+++ b/ipalib/plugins/permission.py
@@ -363,26 +363,17 @@ def _get_filter_attr_info(self, entry):
         # type
         if ipapermtargetfilter and ipapermlocation:
             for obj in self.api.Object():
-                filter_objectclasses = getattr(
-                    obj, 'permission_filter_objectclasses', None)
-                if not filter_objectclasses:
+                filt = self.make_type_filter(obj)
+                if not filt:
                     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:
+                if filt in ipapermtargetfilter:
                     result['type'] = [unicode(obj.name)]
-                    implicit_targetfilters |= objectclass_targetfilters
+                    implicit_targetfilters.add(filt)
                     break
 
         return result
@@ -717,6 +708,17 @@ def upgrade_permission(self, entry, target_entry=None,
             raise ValueError('Cannot convert ACI, %r != %r' % (new_acistring,
                                                                acistring))
 
+    def make_type_filter(self, obj):
+        """Make a filter for a --type based permission from an Object"""
+        objectclasses = getattr(obj, 'permission_filter_objectclasses', None)
+        if not objectclasses:
+            return None
+        filters = [u'(objectclass=%s)' % o for o in objectclasses]
+        if len(filters) == 1:
+            return filters[0]
+        else:
+            return '(|%s)' % ''.join(sorted(filters))
+
     def preprocess_options(self, options,
                            return_filter_ops=False,
                            merge_targetfilter=False):
@@ -808,15 +810,19 @@ def preprocess_options(self, options,
         if 'type' in options:
             objtype = options.pop('type')
             filter_ops['remove'].append(re.compile(r'\(objectclass=.*\)', re.I))
+            filter_ops['remove'].append(re.compile(
+                r'\(\|(\(objectclass=[^(]*\))+\)', re.I))
             if objtype:
                 if 'ipapermlocation' in options:
                     raise errors.ValidationError(
                         name='ipapermlocation',
                         error=_('subtree and type are mutually exclusive'))
                 obj = self.api.Object[objtype.lower()]
-                new_values = [u'(objectclass=%s)' % o
-                              for o in obj.permission_filter_objectclasses]
-                filter_ops['add'].extend(new_values)
+                filt = self.make_type_filter(obj)
+                if not filt:
+                    raise errors.ValidationError(
+                        _('"%s" is not a valid permission type') % objtype)
+                filter_ops['add'].append(filt)
                 container_dn = DN(obj.container_dn, self.api.env.basedn)
                 options['ipapermlocation'] = container_dn
             else:
diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py
index 7394e6282a82ab8554c226253e7510acddd91c71..8c83b1ccca5520327e5c8abc9b9a8355a7fd8cd6 100644
--- a/ipaserver/install/plugins/update_managed_permissions.py
+++ b/ipaserver/install/plugins/update_managed_permissions.py
@@ -516,6 +516,8 @@ def update_entry(self, obj, entry, template,
         template = dict(template)
         template.pop('replaces', None)
         template.pop('replaces_system', None)
+        template.pop('replaces_permissions', None)
+        template.pop('replaces_acis', None)
 
         fixup_function = template.pop('fixup_function', None)
         if fixup_function:
@@ -536,8 +538,7 @@ def update_entry(self, obj, entry, template,
 
         ldap_filter = template.pop('ipapermtargetfilter', None)
         if obj and ldap_filter is None:
-            ldap_filter = ['(objectclass=%s)' % oc
-                           for oc in obj.permission_filter_objectclasses]
+            ldap_filter = [self.api.Object[permission].make_type_filter(obj)]
         entry['ipapermtargetfilter'] = list(ldap_filter or [])
 
         ipapermlocation = template.pop('ipapermlocation', None)
-- 
1.9.3

From c077939b9e6fa05de56c24e04e85539c389f900f Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Thu, 12 Jun 2014 12:01:26 +0200
Subject: [PATCH] Add posixgroup to groups' permission object filter

Private groups don't have the 'ipausergroup' objectclass.
Add posixgroup to the objectclass filters to make
"--type group" permissions apply to all groups.

https://fedorahosted.org/freeipa/ticket/4372
---
 ACI.txt                                        |   4 +-
 ipalib/plugins/group.py                        |   2 +-
 ipatests/test_xmlrpc/test_permission_plugin.py | 106 ++++++++++++++++++++++++-
 3 files changed, 105 insertions(+), 7 deletions(-)

diff --git a/ACI.txt b/ACI.txt
index cd19fb90fdd0ac1947393aabfd667e46a6f015fc..d815eb8bbe37fc67d94ffc679b3d2422b5b804e3 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -29,9 +29,9 @@ aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "p
 dn: cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || txtrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example";)(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";)
 dn: cn=System: Read Group Membership,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "member || memberhost || memberof || memberuid || memberuser")(targetfilter = "(objectclass=ipausergroup)")(version 3.0;acl "permission:System: Read Group Membership";allow (compare,read,search) userdn = "ldap:///all";;)
+aci: (targetattr = "member || memberhost || memberof || memberuid || memberuser")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Read Group Membership";allow (compare,read,search) userdn = "ldap:///all";;)
 dn: cn=System: Read Groups,cn=permissions,cn=pbac,dc=ipa,dc=example
-aci: (targetattr = "businesscategory || cn || description || gidnumber || ipaexternalmember || ipauniqueid || mepmanagedby || o || objectclass || ou || owner || seealso")(targetfilter = "(objectclass=ipausergroup)")(version 3.0;acl "permission:System: Read Groups";allow (compare,read,search) userdn = "ldap:///anyone";;)
+aci: (targetattr = "businesscategory || cn || description || gidnumber || ipaexternalmember || ipauniqueid || mepmanagedby || o || objectclass || ou || owner || seealso")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Read Groups";allow (compare,read,search) userdn = "ldap:///anyone";;)
 dn: cn=System: Read HBAC Rules,cn=permissions,cn=pbac,dc=ipa,dc=example
 aci: (targetattr = "accessruletype || accesstime || cn || description || externalhost || hostcategory || ipaenabledflag || ipauniqueid || member || memberhost || memberservice || memberuser || objectclass || servicecategory || sourcehost || sourcehostcategory || usercategory")(targetfilter = "(objectclass=ipahbacrule)")(version 3.0;acl "permission:System: Read HBAC Rules";allow (compare,read,search) userdn = "ldap:///all";;)
 dn: cn=System: Read HBAC Services,cn=permissions,cn=pbac,dc=ipa,dc=example
diff --git a/ipalib/plugins/group.py b/ipalib/plugins/group.py
index 581ee70b635da0f4d85633b7db367229113f9f73..d130f86686e17b8e3cdc5fafabc64fdde4f2dfc4 100644
--- a/ipalib/plugins/group.py
+++ b/ipalib/plugins/group.py
@@ -126,7 +126,7 @@ class group(LDAPObject):
     object_class = ['ipausergroup']
     object_class_config = 'ipagroupobjectclasses'
     possible_objectclasses = ['posixGroup', 'mepManagedEntry', 'ipaExternalGroup']
-    permission_filter_objectclasses = ['ipausergroup']
+    permission_filter_objectclasses = ['posixgroup', 'ipausergroup']
     search_attributes_config = 'ipagroupsearchfields'
     default_attributes = [
         'cn', 'description', 'gidnumber', 'member', 'memberof',
diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py
index feffc2eb1285d173d63a07bb42df8e64f816b618..6ea6c7b1b7a5476afcacc1525145171f995b8b31 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -102,6 +102,8 @@
 nonexistent_dn = DN('cn=does not exist', api.env.basedn)
 admin_dn = DN('uid=admin', users_dn)
 
+group_filter = u'(|(objectclass=ipausergroup)(objectclass=posixgroup))'
+
 
 def verify_permission_aci(name, dn, acistring):
     """Return test dict that verifies the ACI at the given location"""
@@ -1927,7 +1929,7 @@ class test_permission_sync_attributes(Declarative):
         verify_permission_aci(
             permission1, groups_dn,
             '(targetattr = "sn")' +
-            '(targetfilter = "(objectclass=ipausergroup)")'
+            '(targetfilter = "%s")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
@@ -1962,7 +1964,103 @@ class test_permission_sync_attributes(Declarative):
             permission1, groups_dn,
             '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
-            '(targetfilter = "(objectclass=ipausergroup)")'
+            '(targetfilter = "%s")' % group_filter +
+            '(version 3.0;acl "permission:%s";' % permission1 +
+            'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
+        ),
+
+        dict(
+            desc='Set extra targetfilter on %r' % permission1,
+            command=(
+                'permission_mod', [permission1], dict(
+                    extratargetfilter=u'(cn=blabla)',
+                )
+            ),
+            expected=dict(
+                value=permission1,
+                summary=u'Modified permission "%s"' % permission1,
+                result=dict(
+                    dn=permission1_dn,
+                    cn=[permission1],
+                    objectclass=objectclasses.permission,
+                    type=[u'group'],
+                    ipapermright=[u'write'],
+                    attrs=[u'sn'],
+                    ipapermbindruletype=[u'permission'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermtarget=[DN('cn=editors', groups_dn)],
+                    ipapermlocation=[groups_dn],
+                    targetgroup=[u'editors'],
+                    extratargetfilter=[u'(cn=blabla)'],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1, groups_dn,
+            '(targetattr = "sn")' +
+            '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
+            '(targetfilter = "(&(cn=blabla)%s)")' % group_filter +
+            '(version 3.0;acl "permission:%s";' % permission1 +
+            'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
+        ),
+
+        dict(
+            desc='Retreive %r with --all' % permission1,
+            command=(
+                'permission_show', [permission1], dict(all=True)
+            ),
+            expected=dict(
+                value=permission1,
+                summary=None,
+                result=dict(
+                    dn=permission1_dn,
+                    cn=[permission1],
+                    objectclass=objectclasses.permission,
+                    type=[u'group'],
+                    ipapermright=[u'write'],
+                    attrs=[u'sn'],
+                    ipapermincludedattr=[u'sn'],
+                    ipapermbindruletype=[u'permission'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermtarget=[DN('cn=editors', groups_dn)],
+                    ipapermlocation=[groups_dn],
+                    targetgroup=[u'editors'],
+                    extratargetfilter=[u'(cn=blabla)'],
+                    ipapermtargetfilter=[u'(cn=blabla)', group_filter],
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Set type of %r back to user' % permission1,
+            command=(
+                'permission_mod', [permission1], dict(
+                    type=u'user', ipapermtarget=None,
+                )
+            ),
+            expected=dict(
+                value=permission1,
+                summary=u'Modified permission "%s"' % permission1,
+                result=dict(
+                    dn=permission1_dn,
+                    cn=[permission1],
+                    objectclass=objectclasses.permission,
+                    type=[u'user'],
+                    ipapermright=[u'write'],
+                    attrs=[u'sn'],
+                    ipapermbindruletype=[u'permission'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    extratargetfilter=[u'(cn=blabla)'],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1, users_dn,
+            '(targetattr = "sn")' +
+            '(targetfilter = "(&(cn=blabla)(objectclass=posixaccount))")' +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
@@ -2102,7 +2200,7 @@ class test_permission_sync_nice(Declarative):
         verify_permission_aci(
             permission1, groups_dn,
             '(targetattr = "sn")' +
-            '(targetfilter = "(objectclass=ipausergroup)")' +
+            '(targetfilter = "%s")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
@@ -2137,7 +2235,7 @@ class test_permission_sync_nice(Declarative):
             permission1, groups_dn,
             '(targetattr = "sn")' +
             '(target = "ldap:///%s";)' % DN(('cn', 'editors'), groups_dn) +
-            '(targetfilter = "(objectclass=ipausergroup)")' +
+            '(targetfilter = "%s")' % group_filter +
             '(version 3.0;acl "permission:%s";' % permission1 +
             'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
         ),
-- 
1.9.3

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to