From 5731aa2850d150a90ad84ce5492cd5d8b154e413 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
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=<attrname>=<attrvalue>
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 <abokovoy@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
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