[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Freeipa-devel] [PATCH] 0344-0345 Allow anonymous and all permissions



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

--
PetrĀ³
From 3bd07f08e140d1b34fd58e35ef53bf4e4ce272f7 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori 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.3.1

From 3e1036677014a4da5d427c885b5460039c38b82a Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pviktori 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                    |  31 ++-
 ipatests/test_xmlrpc/test_permission_plugin.py | 267 +++++++++++++++++++++++++
 4 files changed, 308 insertions(+), 5 deletions(-)

diff --git a/API.txt b/API.txt
index 342d7ed6e41b32c1e3695df1eb89b481f9baf48e..22b4034467a2c96f544f6607b1b200c156598516 100644
--- a/API.txt
+++ b/API.txt
@@ -2236,7 +2236,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)
@@ -2292,7 +2292,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)
@@ -2321,7 +2321,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 345faa896c942007f0ab58fb03dbe769c700ce08..1b4a53747d4885f27215d1c4ff008d3a1afe13cc 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..fab9d6641b30058452407fc4500173c2ddf449b0 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,35 @@ class privilege_add_permission(LDAPAddReverseMember):
         ),
     )
 
+    def pre_callback(self, ldap, dn, *keys, **options):
+        # 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..5d8c729756131af2e642a513c3519fecde523f44 100644
--- a/ipatests/test_xmlrpc/test_permission_plugin.py
+++ b/ipatests/test_xmlrpc/test_permission_plugin.py
@@ -2140,3 +2140,270 @@ 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='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.3.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]