sources/ldap: add warning when a property mapping returns None or bytes (#6913)

* sources/ldap: add warning when a property mapping returns None or bytes

closes #6889

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add test

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-09-16 00:37:20 +02:00 committed by GitHub
parent 01eea902ec
commit 583c5e3ba7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 4 deletions

View File

@ -153,8 +153,10 @@ class BaseLDAPSynchronizer:
try: try:
value = mapping.evaluate(user=None, request=None, ldap=kwargs, dn=object_dn) value = mapping.evaluate(user=None, request=None, ldap=kwargs, dn=object_dn)
if value is None: if value is None:
self._logger.warning("property mapping returned None", mapping=mapping)
continue continue
if isinstance(value, (bytes)): if isinstance(value, (bytes)):
self._logger.warning("property mapping returned bytes", mapping=mapping)
continue continue
object_field = mapping.object_field object_field = mapping.object_field
if object_field.startswith("attributes."): if object_field.startswith("attributes."):

View File

@ -9,7 +9,7 @@ from authentik.core.models import Group, User
from authentik.core.tests.utils import create_test_admin_user from authentik.core.tests.utils import create_test_admin_user
from authentik.events.models import Event, EventAction from authentik.events.models import Event, EventAction
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
from authentik.lib.generators import generate_key from authentik.lib.generators import generate_id, generate_key
from authentik.lib.utils.reflection import class_to_path from authentik.lib.utils.reflection import class_to_path
from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
@ -71,6 +71,28 @@ class LDAPSyncTests(TestCase):
) )
self.assertTrue(events.exists()) self.assertTrue(events.exists())
def test_sync_mapping(self):
"""Test property mappings"""
none = LDAPPropertyMapping.objects.create(
name=generate_id(), object_field="none", expression="return None"
)
byte_mapping = LDAPPropertyMapping.objects.create(
name=generate_id(), object_field="bytes", expression="return b''"
)
self.source.property_mappings.set(
LDAPPropertyMapping.objects.filter(
Q(managed__startswith="goauthentik.io/sources/ldap/default")
| Q(managed__startswith="goauthentik.io/sources/ldap/ms")
)
)
self.source.property_mappings.add(none, byte_mapping)
connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD))
# we basically just test that the mappings don't throw errors
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source)
user_sync.sync_full()
def test_sync_users_ad(self): def test_sync_users_ad(self):
"""Test user sync""" """Test user sync"""
self.source.property_mappings.set( self.source.property_mappings.set(
@ -79,7 +101,6 @@ class LDAPSyncTests(TestCase):
| Q(managed__startswith="goauthentik.io/sources/ldap/ms") | Q(managed__startswith="goauthentik.io/sources/ldap/ms")
) )
) )
self.source.save()
connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD)) connection = MagicMock(return_value=mock_ad_connection(LDAP_PASSWORD))
# Create the user beforehand so we can set attributes and check they aren't removed # Create the user beforehand so we can set attributes and check they aren't removed
@ -113,7 +134,6 @@ class LDAPSyncTests(TestCase):
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap") | Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
) )
) )
self.source.save()
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD)) connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection): with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source) user_sync = UserLDAPSynchronizer(self.source)
@ -130,7 +150,6 @@ class LDAPSyncTests(TestCase):
| Q(managed__startswith="goauthentik.io/sources/ldap/openldap") | Q(managed__startswith="goauthentik.io/sources/ldap/openldap")
) )
) )
self.source.save()
connection = MagicMock(return_value=mock_freeipa_connection(LDAP_PASSWORD)) connection = MagicMock(return_value=mock_freeipa_connection(LDAP_PASSWORD))
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection): with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
user_sync = UserLDAPSynchronizer(self.source) user_sync = UserLDAPSynchronizer(self.source)