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>
This commit is contained in:
Florence Blanc-Renaud
2019-07-23 09:31:53 +02:00
committed by Alexander Bokovoy
parent 80561224ab
commit 27baf35013

View File

@@ -921,7 +921,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 = []
@@ -942,8 +964,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: