providers/ldap: use RDN when using posixGroup's memberUid attribute (#1514)
Use the RDN instead of the FDN when establishing group memberships based on posixGroup's 'memberUid' attribute. fixes #1436 Signed-off-by: Steven Armstrong <steven@armstrong.cc>
This commit is contained in:
parent
c032914092
commit
1c91835a26
|
@ -39,11 +39,17 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||||
if not ak_group:
|
if not ak_group:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
membership_mapping_attribute = LDAP_DISTINGUISHED_NAME
|
||||||
|
if self._source.group_membership_field == "memberUid":
|
||||||
|
# If memberships are based on the posixGroup's 'memberUid'
|
||||||
|
# attribute we use the RDN instead of the FDN to lookup members.
|
||||||
|
membership_mapping_attribute = LDAP_UNIQUENESS
|
||||||
|
|
||||||
users = User.objects.filter(
|
users = User.objects.filter(
|
||||||
Q(**{f"attributes__{LDAP_DISTINGUISHED_NAME}__in": members})
|
Q(**{f"attributes__{membership_mapping_attribute}__in": members})
|
||||||
| Q(
|
| Q(
|
||||||
**{
|
**{
|
||||||
f"attributes__{LDAP_DISTINGUISHED_NAME}__isnull": True,
|
f"attributes__{membership_mapping_attribute}__isnull": True,
|
||||||
"ak_groups__in": [ak_group],
|
"ak_groups__in": [ak_group],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -77,5 +77,24 @@ def mock_slapd_connection(password: str) -> Connection:
|
||||||
"objectClass": "person",
|
"objectClass": "person",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
# Group with posixGroup and memberUid
|
||||||
|
connection.strategy.add_entry(
|
||||||
|
"cn=group-posix,ou=groups,dc=goauthentik,dc=io",
|
||||||
|
{
|
||||||
|
"cn": "group-posix",
|
||||||
|
"objectClass": "posixGroup",
|
||||||
|
"memberUid": ["user-posix"],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
# User with posixAccount
|
||||||
|
connection.strategy.add_entry(
|
||||||
|
"cn=user-posix,ou=users,dc=goauthentik,dc=io",
|
||||||
|
{
|
||||||
|
"userPassword": password,
|
||||||
|
"uid": "user-posix",
|
||||||
|
"cn": "user-posix",
|
||||||
|
"objectClass": "posixAccount",
|
||||||
|
},
|
||||||
|
)
|
||||||
connection.bind()
|
connection.bind()
|
||||||
return connection
|
return connection
|
||||||
|
|
|
@ -137,6 +137,34 @@ class LDAPSyncTests(TestCase):
|
||||||
group = Group.objects.filter(name="group1")
|
group = Group.objects.filter(name="group1")
|
||||||
self.assertTrue(group.exists())
|
self.assertTrue(group.exists())
|
||||||
|
|
||||||
|
def test_sync_groups_openldap_posix_group(self):
|
||||||
|
"""Test posix group sync"""
|
||||||
|
self.source.object_uniqueness_field = "cn"
|
||||||
|
self.source.group_membership_field = "memberUid"
|
||||||
|
self.source.user_object_filter = "(objectClass=posixAccount)"
|
||||||
|
self.source.group_object_filter = "(objectClass=posixGroup)"
|
||||||
|
self.source.property_mappings.set(
|
||||||
|
LDAPPropertyMapping.objects.filter(
|
||||||
|
Q(managed__startswith="goauthentik.io/sources/ldap/default")
|
||||||
|
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.source.property_mappings_group.set(
|
||||||
|
LDAPPropertyMapping.objects.filter(managed="goauthentik.io/sources/ldap/openldap-cn")
|
||||||
|
)
|
||||||
|
self.source.save()
|
||||||
|
connection = PropertyMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||||
|
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||||
|
user_sync = UserLDAPSynchronizer(self.source)
|
||||||
|
user_sync.sync()
|
||||||
|
group_sync = GroupLDAPSynchronizer(self.source)
|
||||||
|
group_sync.sync()
|
||||||
|
membership_sync = MembershipLDAPSynchronizer(self.source)
|
||||||
|
membership_sync.sync()
|
||||||
|
# Test if membership mapping based on memberUid works.
|
||||||
|
posix_group = Group.objects.filter(name="group-posix").first()
|
||||||
|
self.assertTrue(posix_group.users.filter(name="user-posix").exists())
|
||||||
|
|
||||||
def test_tasks_ad(self):
|
def test_tasks_ad(self):
|
||||||
"""Test Scheduled tasks"""
|
"""Test Scheduled tasks"""
|
||||||
self.source.property_mappings.set(
|
self.source.property_mappings.set(
|
||||||
|
|
|
@ -355,7 +355,7 @@ export class LDAPSourceForm extends ModelForm<LDAPSource, string> {
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<p class="pf-c-form__helper-text">
|
<p class="pf-c-form__helper-text">
|
||||||
${t`Field which contains members of a group.`}
|
${t`Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'`}
|
||||||
</p>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
|
|
Reference in a new issue