From f2caafb58ec578002fdf88de9cca5a3f5eaa1b2e Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Jun 08 2020 05:33:42 +0000 Subject: Allow permissions with 'self' bindruletype Make it possible to create a managed permission with ipapermbindruletype="self". The ACI will have bind rule '(userdn = "ldap:///self")'. Example ------- Allow users to modify their own fasTimezone and fasIRCNick attributes: ``` managed_permissions = { "System: Self-Modify FAS user attributes": { "ipapermright": {"write"}, "ipapermtargetfilter": ["(objectclass=fasuser)"], "ipapermbindruletype": "self", "ipapermdefaultattr": ["fasTimezone", "fasIRCNick"], } } ``` See: https://github.com/fedora-infra/freeipa-fas/pull/107 Fixes: https://pagure.io/freeipa/issue/8348 Signed-off-by: Christian Heimes Reviewed-By: Alexander Bokovoy Reviewed-By: Rob Crittenden --- diff --git a/API.txt b/API.txt index 3e65883..291ec1f 100644 --- a/API.txt +++ b/API.txt @@ -3678,7 +3678,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False) option: Str('attrs*') option: Str('extratargetfilter*', cli_name='filter') option: Str('filter*') -option: StrEnum('ipapermbindruletype', autofill=True, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous']) +option: StrEnum('ipapermbindruletype', autofill=True, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous', u'self']) option: DNOrURL('ipapermlocation?', alwaysask=True, autofill=False, cli_name='subtree') option: StrEnum('ipapermright*', alwaysask=True, autofill=False, cli_name='right', values=[u'read', u'search', u'compare', u'write', u'add', u'delete', u'all']) option: DNParam('ipapermtarget?', cli_name='target') @@ -3736,7 +3736,7 @@ option: Str('attrs*', autofill=False) option: Str('cn?', autofill=False, cli_name='name') option: Str('extratargetfilter*', autofill=False, cli_name='filter') option: Str('filter*', autofill=False) -option: StrEnum('ipapermbindruletype?', autofill=False, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous']) +option: StrEnum('ipapermbindruletype?', autofill=False, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous', u'self']) option: Str('ipapermdefaultattr*', autofill=False, cli_name='defaultattrs') option: Str('ipapermexcludedattr*', autofill=False, cli_name='excludedattrs') option: Str('ipapermincludedattr*', autofill=False, cli_name='includedattrs') @@ -3770,7 +3770,7 @@ option: Str('attrs*', autofill=False) option: Str('delattr*', cli_name='delattr') option: Str('extratargetfilter*', autofill=False, cli_name='filter') option: Str('filter*', autofill=False) -option: StrEnum('ipapermbindruletype?', autofill=False, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous']) +option: StrEnum('ipapermbindruletype?', autofill=False, cli_name='bindtype', default=u'permission', values=[u'permission', u'all', u'anonymous', u'self']) option: Str('ipapermexcludedattr*', autofill=False, cli_name='excludedattrs') option: Str('ipapermincludedattr*', autofill=False, cli_name='includedattrs') option: DNOrURL('ipapermlocation?', autofill=False, cli_name='subtree') diff --git a/VERSION.m4 b/VERSION.m4 index 11707d5..15afded 100644 --- a/VERSION.m4 +++ b/VERSION.m4 @@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000) # # ######################################################## define(IPA_API_VERSION_MAJOR, 2) -define(IPA_API_VERSION_MINOR, 237) -# Last change: allow rename a hostgroup +define(IPA_API_VERSION_MINOR, 238) +# Last change: permission ipapermbindruletype=self ######################################################## diff --git a/install/ui/src/freeipa/aci.js b/install/ui/src/freeipa/aci.js index 1c6ed6e..7da67cf 100644 --- a/install/ui/src/freeipa/aci.js +++ b/install/ui/src/freeipa/aci.js @@ -159,7 +159,7 @@ return { { $type: 'radio', name: 'ipapermbindruletype', - options: ['permission', 'all', 'anonymous'] + options: ['permission', 'all', 'anonymous', 'self'] }, { $type: 'rights', @@ -280,7 +280,7 @@ return { { $type: 'radio', name: 'ipapermbindruletype', - options: ['permission', 'all', 'anonymous'], + options: ['permission', 'all', 'anonymous', 'self'], default_value: 'permission' }, { diff --git a/ipaserver/install/plugins/update_managed_permissions.py b/ipaserver/install/plugins/update_managed_permissions.py index 11cbfa8..934009e 100644 --- a/ipaserver/install/plugins/update_managed_permissions.py +++ b/ipaserver/install/plugins/update_managed_permissions.py @@ -635,6 +635,10 @@ class update_managed_permissions(Updater): # Attributes from template bindruletype = template.pop('ipapermbindruletype', 'permission') + if bindruletype not in {"all", "anonymous", "self", "permission"}: + raise ValueError( + f"Invalid ipapermbindruletype '{bindruletype}'" + ) if is_new: entry.single_value['ipapermbindruletype'] = bindruletype diff --git a/ipaserver/plugins/permission.py b/ipaserver/plugins/permission.py index 2a0b482..86ad231 100644 --- a/ipaserver/plugins/permission.py +++ b/ipaserver/plugins/permission.py @@ -279,8 +279,8 @@ class permission(baseldap.LDAPObject): label=_('Bind rule type'), doc=_('Bind rule type'), autofill=True, - values=(u'permission', u'all', u'anonymous'), - default=u'permission', + values=('permission', 'all', 'anonymous', 'self'), + default='permission', flags={'allow_mod_for_managed_permission'}, ), DNOrURL( @@ -600,6 +600,8 @@ class permission(baseldap.LDAPObject): bindrule = 'userdn = "ldap:///all"' elif ipapermbindruletype == 'anonymous': bindrule = 'userdn = "ldap:///anyone"' + elif ipapermbindruletype == 'self': + bindrule = 'userdn = "ldap:///self"' else: raise ValueError(ipapermbindruletype) diff --git a/ipatests/test_xmlrpc/test_permission_plugin.py b/ipatests/test_xmlrpc/test_permission_plugin.py index 04654d0..e1dadc2 100644 --- a/ipatests/test_xmlrpc/test_permission_plugin.py +++ b/ipatests/test_xmlrpc/test_permission_plugin.py @@ -4345,3 +4345,48 @@ class test_autoadd_operational_attrs(Declarative): 'allow (read) groupdn = "ldap:///%s";)' % permission1_dn, ), ] + + +class test_self_bindrule(Declarative): + """Test creation of permission with bindrule self + """ + cleanup_commands = [ + ('permission_del', [permission1], {'force': True}), + ] + + tests = [ + dict( + desc='Create %r' % permission1, + command=( + 'permission_add', [permission1], dict( + ipapermlocation=DN('cn=accounts', api.env.basedn), + ipapermright=u'read', + ipapermbindruletype='self', + attrs=[u'objectclass'], + ) + ), + expected=dict( + value=permission1, + summary=u'Added permission "%s"' % permission1, + result=dict( + dn=permission1_dn, + cn=[permission1], + objectclass=objectclasses.permission, + attrs=[u'objectclass', u'entryusn', u'createtimestamp', + u'modifytimestamp'], + ipapermright=[u'read'], + ipapermbindruletype=[u'self'], + ipapermissiontype=[u'SYSTEM', u'V2'], + ipapermlocation=[DN('cn=accounts', api.env.basedn)], + ), + ), + ), + + verify_permission_aci( + permission1, DN('cn=accounts', api.env.basedn), + '(targetattr = "createtimestamp || entryusn || modifytimestamp ' + + '|| objectclass")' + + '(version 3.0;acl "permission:%s";' % permission1 + + 'allow (read) userdn = "ldap:///self";)', + ), + ]