idviews: handle unqualified ID override lookups from Web UI

First part of the required changes to merge a plugin to manage IPA as
a trusted Active Directory user.

It is not possible to omit ID view in IPA API but a client might specify
empty ID view. Up right now the empty view was considered an error. This
prevented Web UI from resolving ID overrides in a group member adder
dialog.

Default to 'Default Trust View' if the ID view is None or empty string
(''). Do this only for user ID overrides, as we do not support adding
group ID overrides as group members in a plugin to manage IPA as a
trusted Active Directory user[1].

Being a group member means an object in LDAP must have an object class
that allows 'memberOf' attribute because 389-ds 'memberof' plugin will
attempt to link back to the object from the group. Allow use of
'nsMemberOf' object class in ID overrides.

Fixes: https://pagure.io/freeipa/issue/7255

[1] https://github.com/abbra/freeipa-adusers-admins

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Alexander Bokovoy 2020-06-03 12:52:55 +03:00 committed by Rob Crittenden
parent ecc0a96d16
commit 973e0c04e4

View File

@ -91,6 +91,28 @@ ANCHOR_REGEX = re.compile(
)
def normalize_idview_name(value):
if value in (None, '',):
return DEFAULT_TRUST_VIEW_NAME
return value
def handle_idoverride_memberof(self, ldap, dn, found, not_found,
*keys, **options):
if ('idoverrideuser' in options) and ('member' in found):
for id in found['member'].get('idoverrideuser', []):
try:
e = ldap.get_entry(id, ['*'])
if not self.obj.has_objectclass(e['objectclass'],
'nsmemberof'):
add_missing_object_class(ldap, 'nsmemberof',
id, entry_attrs=e, update=True)
except errors.NotFound:
# We are not adding an object here, only modifying existing
continue
return dn
@register()
class idview(LDAPObject):
"""
@ -113,6 +135,7 @@ class idview(LDAPObject):
cli_name='name',
label=_('ID View Name'),
primary_key=True,
normalizer=normalize_idview_name,
),
Str('description?',
cli_name='desc',
@ -733,8 +756,12 @@ class baseidoverride(LDAPObject):
self.backend,
self.override_object,
keys[-1],
fallback_to_ldap=options['fallback_to_ldap']
fallback_to_ldap=options.get('fallback_to_ldap', False)
)
if all([len(keys[:-1]) == 0,
self.override_object == 'user',
anchor.startswith(SID_ANCHOR_PREFIX)]):
keys = (DEFAULT_TRUST_VIEW_NAME, ) + keys
keys = keys[:-1] + (anchor, )
return super(baseidoverride, self).get_dn(*keys, **options)
@ -810,6 +837,12 @@ class baseidoverride(LDAPObject):
rules=ldap.MATCH_ALL
)
def get_primary_key_from_dn(self, dn):
return resolve_anchor_to_object_name(self.backend,
self.override_object,
dn[0].value)
class baseidoverride_add(LDAPCreate):
__doc__ = _('Add a new ID override.')
@ -918,16 +951,18 @@ class idoverrideuser(baseidoverride):
'ipapermdefaultattr': {
'objectClass', 'ipaAnchorUUID', 'uidNumber', 'description',
'homeDirectory', 'uid', 'ipaOriginalUid', 'loginShell', 'gecos',
'gidNumber', 'ipaSshPubkey', 'usercertificate'
'gidNumber', 'ipaSshPubkey', 'usercertificate', 'memberof'
},
},
}
object_class = baseidoverride.object_class + ['ipaUserOverride']
possible_objectclasses = ['ipasshuser', 'ipaSshGroupOfPubKeys']
possible_objectclasses = ['ipasshuser', 'ipaSshGroupOfPubKeys',
'nsmemberof']
default_attributes = baseidoverride.default_attributes + [
'homeDirectory', 'uidNumber', 'uid', 'ipaOriginalUid', 'loginShell',
'ipaSshPubkey', 'gidNumber', 'gecos', 'usercertificate;binary',
'memberofindirect', 'memberof'
]
search_display_attributes = baseidoverride.default_attributes + [
@ -935,6 +970,11 @@ class idoverrideuser(baseidoverride):
'ipaSshPubkey', 'gidNumber', 'gecos',
]
attribute_members = {
'memberof': ['group', 'role'],
'memberofindirect': ['group', 'role'],
}
takes_params = baseidoverride.takes_params + (
Str('uid?',
pattern=PATTERN_GROUPUSER_NAME,