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
This commit is contained in:
Petr Viktorin
2013-10-29 17:01:07 +01:00
committed by Martin Kosek
parent d7f5d58d35
commit 4a64a1f18b
4 changed files with 325 additions and 5 deletions

View File

@@ -2329,7 +2329,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui
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 @@ option: Str('attrs', attribute=False, autofill=False, cli_name='attrs', multival
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 @@ option: Str('attrs', attribute=False, autofill=False, cli_name='attrs', multival
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)

View File

@@ -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 @@ class permission_mod(baseldap.LDAPUpdate):
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.

View File

@@ -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):

View File

@@ -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')
),
]