From 5731aa2850d150a90ad84ce5492cd5d8b154e413 Mon Sep 17 00:00:00 2001 From: Florence Blanc-Renaud Date: Tue, 23 Jul 2019 09:31:53 +0200 Subject: [PATCH] user-stage: transfer all attributes from preserved to stage user The user-stage command is internally implemented as: - user_show(all=True) in order to read the user attributes - loop on the attributes defined as possible to add using stageuser-add and transform them into new options for stageuser_add (for instance stageuser-add provides the option --shell for the attribute loginshell, but there is no option for the attribute businesscategory). - call stageuser_add in order to create a new entry in the active users subtree - user-del to remove the previous entry in the staged users subtree The issue is in the 2nd step. Only the attributes with a stageuser-add option are processed. The logic of the code should be slightly modified, so that all the attributes read in the first step are processed: - if they correspond to an option of stageuser-add, process them like it's currently done. For instance if the entry contains displayname, then it should be processed as --displayName=value in the stageuser-add cmd - if they do not correspond to an option of stageuser-add, add them with --setattr== Note that some attributes may need to be filtered, for instance user-show returns has_password or has_keytab, which do not correspond to attributes in the LDAP entry. Fixes: https://pagure.io/freeipa/issue/7597 Reviewed-By: Alexander Bokovoy Reviewed-By: Rob Crittenden --- ipaserver/plugins/user.py | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py index 980385dc83e93ec4a65726077b34917e21115efa..fbf7b11789c58377366f187211c4e403d0cf7ffe 100644 --- a/ipaserver/plugins/user.py +++ b/ipaserver/plugins/user.py @@ -919,7 +919,29 @@ class user_stage(LDAPMultiQuery): has_output = output.standard_multi_delete msg_summary = _('Staged user account "%(value)s"') + # when moving from preserved to stage, some attributes may be + # present in the preserved entry but cannot be provided to + # stageuser_add + # For instance: dn and uid are derived from LOGIN argument + # has_keytab, has_password, preserved are virtual attributes + # ipauniqueid, krbcanonicalname, sshpubkeyfp, krbextradata + # are automatically generated + # ipacertmapdata can only be provided with user_add_certmapdata + ignore_attrs = [u'dn', u'uid', + u'has_keytab', u'has_password', u'preserved', + u'ipauniqueid', u'krbcanonicalname', + u'sshpubkeyfp', u'krbextradata', + u'ipacertmapdata', + u'nsaccountlock'] + def execute(self, *keys, **options): + + def _build_setattr_arg(key, val): + if isinstance(val, bytes): + return u"{}={}".format(key, val.decode('UTF-8')) + else: + return u"{}={}".format(key, val) + staged = [] failed = [] @@ -940,8 +962,30 @@ class user_stage(LDAPMultiQuery): value = value[0] new_options[param.name] = value + # Some attributes may not be accessible through the Command + # options and need to be added with --setattr + set_attr = [] + for userkey in user.keys(): + if userkey in new_options or userkey in self.ignore_attrs: + continue + value = user[userkey] + + if isinstance(value, (list, tuple)): + for val in value: + set_attr.append(_build_setattr_arg(userkey, val)) + else: + set_attr.append(_build_setattr_arg(userkey, val)) + if set_attr: + new_options[u'setattr'] = set_attr + try: self.api.Command.stageuser_add(*single_keys, **new_options) + # special handling for certmapdata + certmapdata = user.get(u'ipacertmapdata') + if certmapdata: + self.api.Command.stageuser_add_certmapdata( + *single_keys, + ipacertmapdata=certmapdata) try: self.api.Command.user_del(*multi_keys, preserve=False) except errors.ExecutionError: -- 2.20.1