URL: https://github.com/freeipa/freeipa/pull/617 Author: stlaz Title: #617: Allow renaming of sudo and HBAC rules Action: synchronized
To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/617/head:pr617 git checkout pr617
From 1de05a1ae8507aca2fb43a0bccc34a566b7334d7 Mon Sep 17 00:00:00 2001 From: Stanislav Laznicka <slazn...@redhat.com> Date: Thu, 16 Mar 2017 16:22:52 +0100 Subject: [PATCH] Allow renaming of HBAC and sudo rules This allows renaming of some objects that don't necessarily contain their own private key in their DN. TODO: control the check whether DN changed https://pagure.io/freeipa/issue/2466 --- API.txt | 6 ++++-- VERSION.m4 | 4 ++-- ipaserver/plugins/automount.py | 2 +- ipaserver/plugins/baseldap.py | 32 ++++++++++++++++++++------------ ipaserver/plugins/baseuser.py | 2 +- ipaserver/plugins/ca.py | 2 +- ipaserver/plugins/dns.py | 2 +- ipaserver/plugins/group.py | 2 +- ipaserver/plugins/hbacrule.py | 1 + ipaserver/plugins/idviews.py | 6 +++--- ipaserver/plugins/otptoken.py | 2 +- ipaserver/plugins/permission.py | 2 +- ipaserver/plugins/privilege.py | 2 +- ipaserver/plugins/radiusproxy.py | 2 +- ipaserver/plugins/role.py | 2 +- ipaserver/plugins/servicedelegation.py | 2 +- ipaserver/plugins/sudorule.py | 1 + 17 files changed, 42 insertions(+), 30 deletions(-) diff --git a/API.txt b/API.txt index f0bd1b6..7594157 100644 --- a/API.txt +++ b/API.txt @@ -2163,7 +2163,7 @@ output: ListOfEntries('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('truncated', type=[<type 'bool'>]) command: hbacrule_mod/1 -args: 1,16,3 +args: 1,17,3 arg: Str('cn', cli_name='name') option: StrEnum('accessruletype?', autofill=False, cli_name='type', default=u'allow', values=[u'allow', u'deny']) option: Str('addattr*', cli_name='addattr') @@ -2175,6 +2175,7 @@ option: StrEnum('hostcategory?', autofill=False, cli_name='hostcat', values=[u'a option: Bool('ipaenabledflag?', autofill=False) option: Flag('no_members', autofill=True, default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('rename?', cli_name='rename') option: Flag('rights', autofill=True, default=False) option: StrEnum('servicecategory?', autofill=False, cli_name='servicecat', values=[u'all']) option: Str('setattr*', cli_name='setattr') @@ -5402,7 +5403,7 @@ output: ListOfEntries('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('truncated', type=[<type 'bool'>]) command: sudorule_mod/1 -args: 1,20,3 +args: 1,21,3 arg: Str('cn', cli_name='sudorule_name') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) @@ -5419,6 +5420,7 @@ option: StrEnum('ipasudorunasgroupcategory?', autofill=False, cli_name='runasgro option: StrEnum('ipasudorunasusercategory?', autofill=False, cli_name='runasusercat', values=[u'all']) option: Flag('no_members', autofill=True, default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('rename?', cli_name='rename') option: Flag('rights', autofill=True, default=False) option: Str('setattr*', cli_name='setattr') option: Int('sudoorder?', autofill=False, cli_name='order', default=0) diff --git a/VERSION.m4 b/VERSION.m4 index cfac2a9..6c4213d 100644 --- a/VERSION.m4 +++ b/VERSION.m4 @@ -73,8 +73,8 @@ define(IPA_DATA_VERSION, 20100614120000) # # ######################################################## define(IPA_API_VERSION_MAJOR, 2) -define(IPA_API_VERSION_MINOR, 223) -# Last change: Add domain resolution order to ID views +define(IPA_API_VERSION_MINOR, 224) +# Last change: Add rename option to some *_mod commands ######################################################## diff --git a/ipaserver/plugins/automount.py b/ipaserver/plugins/automount.py index c4cf2d6..03f994c 100644 --- a/ipaserver/plugins/automount.py +++ b/ipaserver/plugins/automount.py @@ -456,7 +456,7 @@ class automountkey(LDAPObject): default_attributes = [ 'automountkey', 'automountinformation', 'description' ] - rdn_is_primary_key = True + allow_rename = True rdn_separator = ' ' takes_params = ( diff --git a/ipaserver/plugins/baseldap.py b/ipaserver/plugins/baseldap.py index 79ba7fc..dbe3cbd 100644 --- a/ipaserver/plugins/baseldap.py +++ b/ipaserver/plugins/baseldap.py @@ -36,7 +36,7 @@ from ipalib.util import json_serialize, validate_hostname from ipalib.capabilities import client_has_capability from ipalib.messages import add_message, SearchResultTruncated -from ipapython.dn import DN +from ipapython.dn import DN, RDN from ipapython.version import API_VERSION if six.PY3: @@ -549,7 +549,7 @@ class LDAPObject(Object): rdn_attribute = '' uuid_attribute = '' attribute_members = {} - rdn_is_primary_key = False # Do we need RDN change to do a rename? + allow_rename = False password_attributes = [] # Can bind as this entry (has userPassword or krbPrincipalKey) bindable = False @@ -1384,7 +1384,7 @@ def _get_rename_option(self): def get_options(self): for option in super(LDAPUpdate, self).get_options(): yield option - if self.obj.rdn_is_primary_key: + if self.obj.allow_rename: yield self._get_rename_option() def execute(self, *keys, **options): @@ -1419,15 +1419,19 @@ def execute(self, *keys, **options): _check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), list(entry_attrs), allow_only=False) rdnupdate = False - try: - if self.obj.rdn_is_primary_key and 'rename' in options: - if not options['rename']: - raise errors.ValidationError(name='rename', error=u'can\'t be empty') - entry_attrs[self.obj.primary_key.name] = options['rename'] - - if self.obj.rdn_is_primary_key and self.obj.primary_key.name in entry_attrs: + if 'rename' in options: + if not options['rename']: + raise errors.ValidationError( + name='rename', error=u'can\'t be empty') + entry_attrs[self.obj.primary_key.name] = options['rename'] + + # if setattr was used to change the RDN, the primary_key.name is + # already in entry_attrs + if self.obj.allow_rename and self.obj.primary_key.name in entry_attrs: + # perform RDN change if the primary key is also RDN + if (RDN((self.obj.primary_key.name, keys[-1])) == + entry_attrs.dn[0]): try: - # RDN change new_dn = DN((self.obj.primary_key.name, entry_attrs[self.obj.primary_key.name]), *entry_attrs.dn[1:]) @@ -1435,17 +1439,21 @@ def execute(self, *keys, **options): entry_attrs.dn, new_dn) - rdnkeys = keys[:-1] + (entry_attrs[self.obj.primary_key.name], ) + rdnkeys = (keys[:-1] + + (entry_attrs[self.obj.primary_key.name], )) entry_attrs.dn = self.obj.get_dn(*rdnkeys) options['rdnupdate'] = True rdnupdate = True except errors.EmptyModlist: # Attempt to rename to the current name, ignore pass + except errors.NotFound: + self.obj.handle_not_found(*keys) finally: # Delete the primary_key from entry_attrs either way del entry_attrs[self.obj.primary_key.name] + try: # Exception callbacks will need to test for options['rdnupdate'] # to decide what to do. An EmptyModlist in this context doesn't # mean an error occurred, just that there were no other updates to diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py index 44adc76..bf24dbf 100644 --- a/ipaserver/plugins/baseuser.py +++ b/ipaserver/plugins/baseuser.py @@ -164,7 +164,7 @@ class baseuser(LDAPObject): 'memberof': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'], 'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'], } - rdn_is_primary_key = True + allow_rename = True bindable = True password_attributes = [('userpassword', 'has_password'), ('krbprincipalkey', 'has_keytab')] diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py index f774f78..9bb163d 100644 --- a/ipaserver/plugins/ca.py +++ b/ipaserver/plugins/ca.py @@ -68,7 +68,7 @@ class ca(LDAPObject): 'cn', 'description', 'ipacaid', 'ipacaissuerdn', 'ipacasubjectdn', ] rdn_attribute = 'cn' - rdn_is_primary_key = True + allow_rename = True label = _('Certificate Authorities') label_singular = _('Certificate Authority') diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index 7007928..47ac963 100644 --- a/ipaserver/plugins/dns.py +++ b/ipaserver/plugins/dns.py @@ -3000,7 +3000,7 @@ class dnsrecord(LDAPObject): possible_objectclasses = ['idnsTemplateObject'] permission_filter_objectclasses = ['idnsrecord'] default_attributes = ['idnsname'] + _record_attributes - rdn_is_primary_key = True + allow_rename = True label = _('DNS Resource Records') label_singular = _('DNS Resource Record') diff --git a/ipaserver/plugins/group.py b/ipaserver/plugins/group.py index 218da3c..1fb092d 100644 --- a/ipaserver/plugins/group.py +++ b/ipaserver/plugins/group.py @@ -173,7 +173,7 @@ class group(LDAPObject): 'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'], } - rdn_is_primary_key = True + allow_rename = True managed_permissions = { 'System: Read Groups': { 'replaces_global_anonymous_aci': True, diff --git a/ipaserver/plugins/hbacrule.py b/ipaserver/plugins/hbacrule.py index 60e5e60..2495702 100644 --- a/ipaserver/plugins/hbacrule.py +++ b/ipaserver/plugins/hbacrule.py @@ -141,6 +141,7 @@ class hbacrule(LDAPObject): ] uuid_attribute = 'ipauniqueid' rdn_attribute = 'ipauniqueid' + allow_rename = True attribute_members = { 'memberuser': ['user', 'group'], 'memberhost': ['host', 'hostgroup'], diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py index 6d4ac75..b5ee32c 100644 --- a/ipaserver/plugins/idviews.py +++ b/ipaserver/plugins/idviews.py @@ -97,7 +97,7 @@ class idview(LDAPObject): object_class = ['ipaIDView', 'top'] possible_objectclasses = ['ipaNameResolutionData'] default_attributes = ['cn', 'description', 'ipadomainresolutionorder'] - rdn_is_primary_key = True + allow_rename = True label = _('ID Views') label_singular = _('ID View') @@ -848,7 +848,7 @@ class idoverrideuser(baseidoverride): label = _('User ID overrides') label_singular = _('User ID override') - rdn_is_primary_key = True + allow_rename = True # ID user overrides are bindable because we map SASL GSSAPI # authentication of trusted users to ID user overrides in the @@ -964,7 +964,7 @@ class idoverridegroup(baseidoverride): label = _('Group ID overrides') label_singular = _('Group ID override') - rdn_is_primary_key = True + allow_rename = True permission_filter_objectclasses = ['ipaGroupOverride'] managed_permissions = { diff --git a/ipaserver/plugins/otptoken.py b/ipaserver/plugins/otptoken.py index 98ecbe5..c66f098 100644 --- a/ipaserver/plugins/otptoken.py +++ b/ipaserver/plugins/otptoken.py @@ -143,7 +143,7 @@ class otptoken(LDAPObject): relationships = { 'managedby': ('Managed by', 'man_by_', 'not_man_by_'), } - rdn_is_primary_key = True + allow_rename = True label = _('OTP Tokens') label_singular = _('OTP Token') diff --git a/ipaserver/plugins/permission.py b/ipaserver/plugins/permission.py index dd2a018..977c6fe 100644 --- a/ipaserver/plugins/permission.py +++ b/ipaserver/plugins/permission.py @@ -188,7 +188,7 @@ class permission(baseldap.LDAPObject): 'member': ['privilege'], 'memberindirect': ['role'], } - rdn_is_primary_key = True + allow_rename = True managed_permissions = { 'System: Read Permissions': { 'replaces_global_anonymous_aci': True, diff --git a/ipaserver/plugins/privilege.py b/ipaserver/plugins/privilege.py index b3afbd2..01d5396 100644 --- a/ipaserver/plugins/privilege.py +++ b/ipaserver/plugins/privilege.py @@ -101,7 +101,7 @@ class privilege(LDAPObject): reverse_members = { 'member': ['permission'], } - rdn_is_primary_key = True + allow_rename = True managed_permissions = { 'System: Read Privileges': { 'replaces_global_anonymous_aci': True, diff --git a/ipaserver/plugins/radiusproxy.py b/ipaserver/plugins/radiusproxy.py index 3391b8a..be77c62 100644 --- a/ipaserver/plugins/radiusproxy.py +++ b/ipaserver/plugins/radiusproxy.py @@ -101,7 +101,7 @@ class radiusproxy(LDAPObject): 'ipatokenradiustimeout', 'ipatokenradiusretries', 'ipatokenusermapattribute' ] search_attributes = ['cn', 'description', 'ipatokenradiusserver'] - rdn_is_primary_key = True + allow_rename = True label = _('RADIUS Servers') label_singular = _('RADIUS Server') diff --git a/ipaserver/plugins/role.py b/ipaserver/plugins/role.py index 5d0d1f8..e7f115c 100644 --- a/ipaserver/plugins/role.py +++ b/ipaserver/plugins/role.py @@ -92,7 +92,7 @@ class role(LDAPObject): reverse_members = { 'member': ['privilege'], } - rdn_is_primary_key = True + allow_rename = True managed_permissions = { 'System: Read Roles': { 'replaces_global_anonymous_aci': True, diff --git a/ipaserver/plugins/servicedelegation.py b/ipaserver/plugins/servicedelegation.py index c8052e9..4f94924 100644 --- a/ipaserver/plugins/servicedelegation.py +++ b/ipaserver/plugins/servicedelegation.py @@ -138,7 +138,7 @@ class servicedelegation(LDAPObject): }, } - rdn_is_primary_key = True + allow_rename = True takes_params = ( Str( diff --git a/ipaserver/plugins/sudorule.py b/ipaserver/plugins/sudorule.py index 9077107..28c3f21 100644 --- a/ipaserver/plugins/sudorule.py +++ b/ipaserver/plugins/sudorule.py @@ -145,6 +145,7 @@ class sudorule(LDAPObject): ] uuid_attribute = 'ipauniqueid' rdn_attribute = 'ipauniqueid' + allow_rename = True attribute_members = { 'memberuser': ['user', 'group'], 'memberhost': ['host', 'hostgroup'],
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code