On 01/03/2014 04:44 PM, Martin Kosek wrote:
On 12/16/2013 12:46 PM, Petr Viktorin wrote:
Hello,
The next step in permission effort is small since the groundwork is already 
done.

This adds API/CLI for anonymous&all permissions, and disables adding these to
privileges.

Ticket: https://fedorahosted.org/freeipa/ticket/4032
Design: http://www.freeipa.org/page/V3/Anonymous_and_All_permissions


This looks strange

# ipa permission-add anon --type=user --permissions=read --attrs=description
--bindtype=anonymous

# ipa privilege-add-permission foo --perm=
ipa: ERROR: invalid 'permission':
cannot add permission "anon" with bindtype "anonymous" to a privilege

(I know, I am nitpicking again).

Otherwise I think the patch is OK.

Martin

Good catch, thanks.
Updated patches attached.


--
PetrĀ³
From 62e250ee632893b1e675775d30837ade82c87208 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 29 Oct 2013 16:28:17 +0100
Subject: [PATCH] Use new registration API in the privilege plugin

---
 ipalib/plugins/privilege.py | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/ipalib/plugins/privilege.py b/ipalib/plugins/privilege.py
index ba2428736c9cdd022680fc69e97d0b583a16a2d1..694e1184f857ef6b91a984db99fdca69bfc3a845 100644
--- a/ipalib/plugins/privilege.py
+++ b/ipalib/plugins/privilege.py
@@ -19,6 +19,7 @@
 
 from ipalib.plugins.baseldap import *
 from ipalib import api, _, ngettext
+from ipalib.plugable import Registry
 
 __doc__ = _("""
 Privileges
@@ -41,6 +42,10 @@
 See role and permission for additional information.
 """)
 
+register = Registry()
+
+
+@register()
 class privilege(LDAPObject):
     """
     Privilege object.
@@ -75,33 +80,29 @@ class privilege(LDAPObject):
         ),
     )
 
-api.register(privilege)
-
 
+@register()
 class privilege_add(LDAPCreate):
     __doc__ = _('Add a new privilege.')
 
     msg_summary = _('Added privilege "%(value)s"')
 
-api.register(privilege_add)
-
 
+@register()
 class privilege_del(LDAPDelete):
     __doc__ = _('Delete a privilege.')
 
     msg_summary = _('Deleted privilege "%(value)s"')
 
-api.register(privilege_del)
-
 
+@register()
 class privilege_mod(LDAPUpdate):
     __doc__ = _('Modify a privilege.')
 
     msg_summary = _('Modified privilege "%(value)s"')
 
-api.register(privilege_mod)
-
 
+@register()
 class privilege_find(LDAPSearch):
     __doc__ = _('Search for privileges.')
 
@@ -109,32 +110,28 @@ class privilege_find(LDAPSearch):
         '%(count)d privilege matched', '%(count)d privileges matched', 0
     )
 
-api.register(privilege_find)
-
 
+@register()
 class privilege_show(LDAPRetrieve):
     __doc__ = _('Display information about a privilege.')
 
-api.register(privilege_show)
-
 
+@register()
 class privilege_add_member(LDAPAddMember):
     __doc__ = _('Add members to a privilege.')
 
     NO_CLI=True
 
-api.register(privilege_add_member)
-
 
+@register()
 class privilege_remove_member(LDAPRemoveMember):
     """
     Remove members from a privilege
     """
     NO_CLI=True
 
-api.register(privilege_remove_member)
-
 
+@register()
 class privilege_add_permission(LDAPAddReverseMember):
     __doc__ = _('Add permissions to a privilege.')
 
@@ -155,9 +152,8 @@ class privilege_add_permission(LDAPAddReverseMember):
         ),
     )
 
-api.register(privilege_add_permission)
-
 
+@register()
 class privilege_remove_permission(LDAPRemoveReverseMember):
     __doc__ = _('Remove permissions from a privilege.')
 
@@ -179,5 +175,3 @@ class privilege_remove_permission(LDAPRemoveReverseMember):
             doc=_('Number of permissions removed'),
         ),
     )
-
-api.register(privilege_remove_permission)
-- 
1.8.4.2

From 646bc9ae13171b837b2e8c6fd5d5d81cee6e079e Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Tue, 29 Oct 2013 17:01:07 +0100
Subject: [PATCH] Allow anonymous and all permissions

Disallow adding permissions with non-default bindtype to privileges

Ticket: https://fedorahosted.org/freeipa/ticket/4032
Design: http://www.freeipa.org/page/V3/Anonymous_and_All_permissions
---
 API.txt                                        |   6 +-
 ipalib/plugins/permission.py                   |   9 +-
 ipalib/plugins/privilege.py                    |  33 ++-
 ipatests/test_xmlrpc/test_permission_plugin.py | 282 +++++++++++++++++++++++++
 4 files changed, 325 insertions(+), 5 deletions(-)

diff --git a/API.txt b/API.txt
index 3bb1b76ac9a53449d46979d554cce556d21e1323..a6c3aed82370d690a678a034b0eea85d4f85b45f 100644
--- a/API.txt
+++ b/API.txt
@@ -2329,7 +2329,7 @@ command: permission_add
 option: Str('attrs', attribute=False, cli_name='attrs', multivalue=True, required=False)
 option: Str('filter', attribute=False, cli_name='filter', multivalue=True, required=False)
 option: Str('ipapermallowedattr', attribute=True, cli_name='attrs', multivalue=True, required=False)
-option: StrEnum('ipapermbindruletype', attribute=True, autofill=True, cli_name='bindtype', default=u'permission', multivalue=False, required=True, values=(u'permission',))
+option: StrEnum('ipapermbindruletype', attribute=True, autofill=True, cli_name='bindtype', default=u'permission', multivalue=False, required=True, values=(u'permission', u'all', u'anonymous'))
 option: DNOrURL('ipapermlocation', alwaysask=True, attribute=True, autofill=False, cli_name='subtree', multivalue=False, query=False, required=False)
 option: StrEnum('ipapermright', attribute=True, cli_name='permissions', multivalue=True, required=False, values=(u'read', u'search', u'compare', u'write', u'add', u'delete', u'all'))
 option: DNParam('ipapermtarget', attribute=True, cli_name='target', multivalue=False, required=False)
@@ -2385,7 +2385,7 @@ command: permission_find
 option: Str('cn', attribute=True, autofill=False, cli_name='name', multivalue=False, pattern='^[-_ a-zA-Z0-9.]+$', primary_key=True, query=True, required=False)
 option: Str('filter', attribute=False, autofill=False, cli_name='filter', multivalue=True, query=True, required=False)
 option: Str('ipapermallowedattr', attribute=True, autofill=False, cli_name='attrs', multivalue=True, query=True, required=False)
-option: StrEnum('ipapermbindruletype', attribute=True, autofill=False, cli_name='bindtype', default=u'permission', multivalue=False, query=True, required=False, values=(u'permission',))
+option: StrEnum('ipapermbindruletype', attribute=True, autofill=False, cli_name='bindtype', default=u'permission', multivalue=False, query=True, required=False, values=(u'permission', u'all', u'anonymous'))
 option: DNOrURL('ipapermlocation', attribute=True, autofill=False, cli_name='subtree', multivalue=False, query=True, required=False)
 option: StrEnum('ipapermright', attribute=True, autofill=False, cli_name='permissions', multivalue=True, query=True, required=False, values=(u'read', u'search', u'compare', u'write', u'add', u'delete', u'all'))
 option: DNParam('ipapermtarget', attribute=True, autofill=False, cli_name='target', multivalue=False, query=True, required=False)
@@ -2414,7 +2414,7 @@ command: permission_mod
 option: Str('delattr*', cli_name='delattr', exclude='webui')
 option: Str('filter', attribute=False, autofill=False, cli_name='filter', multivalue=True, required=False)
 option: Str('ipapermallowedattr', attribute=True, autofill=False, cli_name='attrs', multivalue=True, required=False)
-option: StrEnum('ipapermbindruletype', attribute=True, autofill=False, cli_name='bindtype', default=u'permission', multivalue=False, required=False, values=(u'permission',))
+option: StrEnum('ipapermbindruletype', attribute=True, autofill=False, cli_name='bindtype', default=u'permission', multivalue=False, required=False, values=(u'permission', u'all', u'anonymous'))
 option: DNOrURL('ipapermlocation', attribute=True, autofill=False, cli_name='subtree', multivalue=False, required=False)
 option: StrEnum('ipapermright', attribute=True, autofill=False, cli_name='permissions', multivalue=True, required=False, values=(u'read', u'search', u'compare', u'write', u'add', u'delete', u'all'))
 option: DNParam('ipapermtarget', attribute=True, autofill=False, cli_name='target', multivalue=False, required=False)
diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py
index fef640c37bc34f53376fad3a1b943bb37f677167..204574697beac40917f3671787146f421d84c93b 100644
--- a/ipalib/plugins/permission.py
+++ b/ipalib/plugins/permission.py
@@ -180,7 +180,7 @@ class permission(baseldap.LDAPObject):
             label=_('Bind rule type'),
             doc=_('Bind rule type'),
             autofill=True,
-            values=(u'permission',),
+            values=(u'permission', u'all', u'anonymous'),
             default=u'permission',
         ),
         DNOrURL(
@@ -775,6 +775,13 @@ def pre_callback(self, ldap, dn, entry, attrs_list, *keys, **options):
         self.obj.reject_system(old_entry)
         self.obj.upgrade_permission(old_entry)
 
+        # Check setting bindtype for an assigned permission
+        if options.get('ipapermbindruletype') and old_entry.get('member'):
+            raise errors.ValidationError(
+                name='ipapermbindruletype',
+                error=_('cannot set bindtype for a permission that is '
+                        'assigned to a privilege'))
+
         # Since `entry` only contains the attributes we are currently changing,
         # it cannot be used directly to generate an ACI.
         # First we need to copy the original data into it.
diff --git a/ipalib/plugins/privilege.py b/ipalib/plugins/privilege.py
index 694e1184f857ef6b91a984db99fdca69bfc3a845..678eb2416837765c82eca7ba32ec3b9d83e20b6a 100644
--- a/ipalib/plugins/privilege.py
+++ b/ipalib/plugins/privilege.py
@@ -18,7 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from ipalib.plugins.baseldap import *
-from ipalib import api, _, ngettext
+from ipalib import api, _, ngettext, errors
 from ipalib.plugable import Registry
 
 __doc__ = _("""
@@ -152,6 +152,37 @@ class privilege_add_permission(LDAPAddReverseMember):
         ),
     )
 
+    def pre_callback(self, ldap, dn, *keys, **options):
+        if options.get('permission'):
+            # We can only add permissions with bind rule type set to
+            # "permission" (or old-style permissions)
+            ldapfilter = ldap.combine_filters(rules='&', filters=[
+                '(objectClass=ipaPermissionV2)',
+                '(!(ipaPermBindRuleType=permission))',
+                ldap.make_filter_from_attr('cn', options['permission'],
+                                           rules='|'),
+            ])
+            try:
+                entries, truncated = ldap.find_entries(
+                    filter=ldapfilter,
+                    attrs_list=['cn', 'ipapermbindruletype'],
+                    base_dn=DN(self.api.env.container_permission,
+                               self.api.env.basedn),
+                    size_limit=1)
+            except errors.NotFound:
+                pass
+            else:
+                entry = entries[0]
+                message = _('cannot add permission "%(perm)s" with bindtype '
+                            '"%(bindtype)s" to a privilege')
+                raise errors.ValidationError(
+                    name='permission',
+                    error=message % {
+                        'perm': entry.single_value['cn'],
+                        'bindtype': entry.single_value.get(
+                            'ipapermbindruletype', 'permission')})
+        return dn
+
 
 @register()
 class privilege_remove_permission(LDAPRemoveReverseMember):
diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py
index e1a7cd8ee15349b353979c3cfca0c5b027580ee3..6564cbc9b5da4adfe582a753947d7fccdbbf4cb1 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -2140,3 +2140,285 @@ class test_permission_legacy(Declarative):
             ),
         ),
     ]
+
+
+class test_permission_bindtype(Declarative):
+    cleanup_commands = [
+        ('permission_del', [permission1], {'force': True}),
+        ('permission_del', [permission1_renamed], {'force': True}),
+        ('privilege_del', [privilege1], {}),
+    ]
+
+    tests = [
+        dict(
+            desc='Create anonymous %r' % permission1,
+            command=(
+                'permission_add', [permission1], dict(
+                    type=u'user',
+                    ipapermright=u'write',
+                    ipapermbindruletype=u'anonymous',
+                )
+            ),
+            expected=dict(
+                value=permission1,
+                summary=u'Added permission "%s"' % permission1,
+                result=dict(
+                    dn=permission1_dn,
+                    cn=[permission1],
+                    objectclass=objectclasses.permission,
+                    type=[u'user'],
+                    ipapermright=[u'write'],
+                    ipapermbindruletype=[u'anonymous'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    ipapermtarget=[DN('uid=*', users_dn)],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1, users_dn,
+            '(target = "ldap:///%s";)' % DN(('uid', '*'), users_dn) +
+            '(version 3.0;acl "permission:%s";' % permission1 +
+            'allow (write) userdn = "ldap:///anyone";;)',
+        ),
+
+        dict(
+            desc='Create %r' % privilege1,
+            command=('privilege_add', [privilege1],
+                dict(description=u'privilege desc. 1')
+            ),
+            expected=dict(
+                value=privilege1,
+                summary=u'Added privilege "%s"' % privilege1,
+                result=dict(
+                    dn=privilege1_dn,
+                    cn=[privilege1],
+                    description=[u'privilege desc. 1'],
+                    objectclass=objectclasses.privilege,
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Try to add %r to %r' % (permission1, privilege1),
+            command=(
+                'privilege_add_permission', [privilege1], dict(
+                    permission=[permission1],
+                )
+            ),
+            expected=errors.ValidationError(
+                name='permission',
+                error=u'cannot add permission "%s" with bindtype "%s" to a '
+                       'privilege' % (permission1, 'anonymous')),
+        ),
+
+        dict(
+            desc='Change binddn of %r to all' % permission1,
+            command=(
+                'permission_mod', [permission1], dict(
+                    type=u'user',
+                    ipapermbindruletype=u'all',
+                )
+            ),
+            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'],
+                    ipapermbindruletype=[u'all'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    ipapermtarget=[DN('uid=*', users_dn)],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1, users_dn,
+            '(target = "ldap:///%s";)' % DN(('uid', '*'), users_dn) +
+            '(version 3.0;acl "permission:%s";' % permission1 +
+            'allow (write) userdn = "ldap:///all";;)',
+        ),
+
+        dict(
+            desc='Try to add %r to %r' % (permission1, privilege1),
+            command=(
+                'privilege_add_permission', [privilege1], dict(
+                    permission=[permission1],
+                )
+            ),
+            expected=errors.ValidationError(
+                name='permission',
+                error=u'cannot add permission "%s" with bindtype "%s" to a '
+                       'privilege' % (permission1, 'all')),
+        ),
+
+        dict(
+            desc='Search for %r using --bindtype' % permission1,
+            command=('permission_find', [], {'ipapermbindruletype': u'all'}),
+            expected=dict(
+                count=1,
+                truncated=False,
+                summary=u'1 permission matched',
+                result=[
+                    dict(
+                        dn=permission1_dn,
+                        cn=[permission1],
+                        type=[u'user'],
+                        ipapermright=[u'write'],
+                        ipapermbindruletype=[u'all'],
+                        objectclass=objectclasses.permission,
+                        ipapermissiontype=[u'SYSTEM', u'V2'],
+                        ipapermlocation=[users_dn],
+                        ipapermtarget=[DN('uid=*', users_dn)],
+                    ),
+                ],
+            ),
+        ),
+
+        dict(
+            desc='Add zero permissions to %r' % (privilege1),
+            command=('privilege_add_permission', [privilege1], {}),
+            expected=dict(
+                completed=0,
+                failed=dict(member=dict(permission=[])),
+                result=dict(
+                    dn=privilege1_dn,
+                    cn=[privilege1],
+                    description=[u'privilege desc. 1'],
+                    objectclass=objectclasses.privilege,
+                ),
+            ),
+        ),
+
+        dict(
+            desc='Rename %r to permission %r' % (permission1,
+                                                 permission1_renamed),
+            command=(
+                'permission_mod', [permission1], dict(rename=permission1_renamed)
+            ),
+            expected=dict(
+                value=permission1,
+                summary=u'Modified permission "%s"' % permission1,
+                result=dict(
+                    dn=permission1_renamed_dn,
+                    cn=[permission1_renamed],
+                    type=[u'user'],
+                    objectclass=objectclasses.permission,
+                    ipapermright=[u'write'],
+                    ipapermbindruletype=[u'all'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    ipapermtarget=[DN('uid=*', users_dn)],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1_renamed, users_dn,
+            '(target = "ldap:///%s";)' % DN(('uid', '*'), users_dn) +
+            '(version 3.0;acl "permission:%s";' % permission1_renamed +
+            'allow (write) userdn = "ldap:///all";;)',
+        ),
+
+        dict(
+            desc='Reset binddn of %r to permission' % permission1_renamed,
+            command=(
+                'permission_mod', [permission1_renamed], dict(
+                    type=u'user',
+                    ipapermbindruletype=u'permission',
+                )
+            ),
+            expected=dict(
+                value=permission1_renamed,
+                summary=u'Modified permission "%s"' % permission1_renamed,
+                result=dict(
+                    dn=permission1_renamed_dn,
+                    cn=[permission1_renamed],
+                    objectclass=objectclasses.permission,
+                    type=[u'user'],
+                    ipapermright=[u'write'],
+                    ipapermbindruletype=[u'permission'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    ipapermtarget=[DN('uid=*', users_dn)],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1_renamed, users_dn,
+            '(target = "ldap:///%s";)' % DN(('uid', '*'), users_dn) +
+            '(version 3.0;acl "permission:%s";' % permission1_renamed +
+            'allow (write) groupdn = "ldap:///%s";;)' % permission1_renamed_dn,
+        ),
+
+        dict(
+            desc='Rename %r back to %r' % (permission1_renamed, permission1),
+            command=(
+                'permission_mod', [permission1_renamed],
+                dict(rename=permission1)
+            ),
+            expected=dict(
+                value=permission1_renamed,
+                summary=u'Modified permission "%s"' % permission1_renamed,
+                result=dict(
+                    dn=permission1_dn,
+                    cn=[permission1],
+                    type=[u'user'],
+                    objectclass=objectclasses.permission,
+                    ipapermright=[u'write'],
+                    ipapermbindruletype=[u'permission'],
+                    ipapermissiontype=[u'SYSTEM', u'V2'],
+                    ipapermlocation=[users_dn],
+                    ipapermtarget=[DN('uid=*', users_dn)],
+                ),
+            ),
+        ),
+
+        verify_permission_aci(
+            permission1, users_dn,
+            '(target = "ldap:///%s";)' % DN(('uid', '*'), users_dn) +
+            '(version 3.0;acl "permission:%s";' % permission1 +
+            'allow (write) groupdn = "ldap:///%s";;)' % permission1_dn,
+        ),
+
+        dict(
+            desc='Add %r to %r' % (permission1, privilege1),
+            command=(
+                'privilege_add_permission', [privilege1], dict(
+                    permission=[permission1],
+                )
+            ),
+            expected=dict(
+                completed=1,
+                failed=dict(member=dict(permission=[])),
+                result=dict(
+                    dn=privilege1_dn,
+                    cn=[privilege1],
+                    description=[u'privilege desc. 1'],
+                    memberof_permission=[permission1],
+                    objectclass=objectclasses.privilege,
+                )
+            ),
+        ),
+
+        dict(
+            desc='Try to change binddn of %r to anonymous' % permission1,
+            command=(
+                'permission_mod', [permission1], dict(
+                    type=u'user',
+                    ipapermbindruletype=u'anonymous',
+                )
+            ),
+            expected=errors.ValidationError(
+                name='ipapermbindruletype',
+                error=u'cannot set bindtype for a permission that is '
+                    'assigned to a privilege')
+        ),
+    ]
-- 
1.8.4.2

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

Reply via email to