URL: https://github.com/freeipa/freeipa/pull/5720 Author: flo-renaud Title: #5720: [Backport][ipa-4-9] Retrieve the user objectclasses when checking for existence Action: opened
PR body: """ This PR was opened automatically because PR #5707 was pushed to master and backport to ipa-4-9 is required. """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/5720/head:pr5720 git checkout pr5720
From 495a6ed7e9833698f801bd66f84facc59e90cb1e Mon Sep 17 00:00:00 2001 From: Rob Crittenden <rcrit...@redhat.com> Date: Tue, 2 Mar 2021 15:11:18 -0500 Subject: [PATCH] Retrieve the user objectclasses when checking for existence This saves at least one search per user-mod because the current set of objectclasses are verified to ensure they are complete on each update. So always retrieve them in get_either_dn(). They are used by every call but there is negligible overhead in retrieving this from LDAP. https://pagure.io/freeipa/issue/8801 Signed-off-by: Rob Crittenden <rcrit...@redhat.com> --- ipaserver/plugins/user.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py index 775eb6346eb..6f7facb5380 100644 --- a/ipaserver/plugins/user.py +++ b/ipaserver/plugins/user.py @@ -443,15 +443,16 @@ def get_delete_dn(self, *keys, **options): def get_either_dn(self, *keys, **options): ''' - Returns the DN of a user + Returns the DN of a user and their objectclasses The user can be active (active container) or delete (delete container) If the user does not exist, returns the Active user DN ''' ldap = self.backend + oc = [] # Check that this value is a Active user try: active_dn = self.get_dn(*keys, **options) - ldap.get_entry(active_dn, ['dn']) + oc = ldap.get_entry(active_dn, ['dn', 'objectclass'])['objectclass'] # The Active user exists dn = active_dn @@ -459,7 +460,9 @@ def get_either_dn(self, *keys, **options): # Check that this value is a Delete user delete_dn = self.get_delete_dn(*keys, **options) try: - ldap.get_entry(delete_dn, ['dn']) + oc = ldap.get_entry( + delete_dn, ['dn', 'objectclass'] + )['objectclass'] # The Delete user exists dn = delete_dn @@ -467,7 +470,7 @@ def get_either_dn(self, *keys, **options): # The user is neither Active/Delete -> returns that Active DN dn = active_dn - return dn + return dn, oc def _normalize_manager(self, manager): """ @@ -688,7 +691,7 @@ class user_del(baseuser_del): def _preserve_user(self, pkey, delete_container, **options): assert isinstance(delete_container, DN) - dn = self.obj.get_either_dn(pkey, **options) + dn, _oc = self.obj.get_either_dn(pkey, **options) delete_dn = DN(dn[0], delete_container) ldap = self.obj.backend logger.debug("preserve move %s -> %s", dn, delete_dn) @@ -744,7 +747,7 @@ def _preserve_user(self, pkey, delete_container, **options): self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs) def pre_callback(self, ldap, dn, *keys, **options): - dn = self.obj.get_either_dn(*keys, **options) + dn, _oc = self.obj.get_either_dn(*keys, **options) # For User life Cycle: user-del is a common plugin # command to delete active user (active container) and @@ -819,7 +822,9 @@ def get_options(self): yield option def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - dn = self.obj.get_either_dn(*keys, **options) + dn, oc = self.obj.get_either_dn(*keys, **options) + if 'objectclass' not in entry_attrs and 'rename' not in options: + entry_attrs.update({'objectclass': oc}) self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys, **options) validate_nsaccountlock(entry_attrs) @@ -901,7 +906,7 @@ class user_show(baseuser_show): ) def pre_callback(self, ldap, dn, attrs_list, *keys, **options): - dn = self.obj.get_either_dn(*keys, **options) + dn, _oc = self.obj.get_either_dn(*keys, **options) self.pre_common_callback(ldap, dn, attrs_list, *keys, **options) return dn @@ -923,7 +928,7 @@ def execute(self, *keys, **options): ldap = self.obj.backend # First check that the user exists and is a delete one - delete_dn = self.obj.get_either_dn(*keys, **options) + delete_dn, _oc = self.obj.get_either_dn(*keys, **options) try: self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn) except errors.NotFound: @@ -1063,7 +1068,7 @@ def execute(self, *keys, **options): check_protected_member(keys[-1]) - dn = self.obj.get_either_dn(*keys, **options) + dn, _oc = self.obj.get_either_dn(*keys, **options) ldap.deactivate_entry(dn) return dict( @@ -1083,7 +1088,7 @@ class user_enable(LDAPQuery): def execute(self, *keys, **options): ldap = self.obj.backend - dn = self.obj.get_either_dn(*keys, **options) + dn, _oc = self.obj.get_either_dn(*keys, **options) ldap.activate_entry(dn) @@ -1107,7 +1112,7 @@ class user_unlock(LDAPQuery): msg_summary = _('Unlocked account "%(value)s"') def execute(self, *keys, **options): - dn = self.obj.get_either_dn(*keys, **options) + dn, _oc = self.obj.get_either_dn(*keys, **options) entry = self.obj.backend.get_entry( dn, ['krbLastAdminUnlock', 'krbLoginFailedCount']) @@ -1191,7 +1196,7 @@ def get_args(self): def execute(self, *keys, **options): ldap = self.obj.backend - dn = self.api.Object.user.get_either_dn(*keys, **options) + dn, _oc = self.api.Object.user.get_either_dn(*keys, **options) attr_list = ['krbloginfailedcount', 'krblastsuccessfulauth', 'krblastfailedauth', 'nsaccountlock'] disabled = False
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure