From 3cdd9e7d29320796fff4fb3c5460cce5a1020eb3 Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Mon, 15 Feb 2021 14:32:38 +0100 Subject: [PATCH] ldap: log missing group dn when mapped to a role (#50928) --- src/authentic2/backends/ldap_backend.py | 22 ++++++++++++++++++++++ tests/test_ldap.py | 8 ++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index 28f212e31..1c1c74cef 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -589,6 +589,27 @@ class LDAPBackend(object): message = str(vars(c)) log.info('ldap: bind error with authz_id "%s" -> "%s"', authz_id, message) + @classmethod + def check_group_to_role_mappings(cls, block): + group_to_role_mapping = block.get('group_to_role_mapping') + if not group_to_role_mapping: + return + for conn in cls.get_connections(block): + existing_groups = cls.get_groups_dns(conn, block) + for group_dn, role_slugs in group_to_role_mapping: + if group_dn in existing_groups: + continue + log.warning('ldap: unknown group "%s" mapped to a role', group_dn) + + @classmethod + def get_groups_dns(cls, conn, block): + group_base_dn = block['group_basedn'] or block['basedn'] + # 1.1 is special attribute meaning, "no attribute requested" + results = conn.search_s(group_base_dn, ldap.SCOPE_SUBTREE, + block['group_filter'], ['1.1']) + results = cls.normalize_ldap_results(results) + return set([group_dn for group_dn, attrs in results]) + def authenticate(self, request=None, username=None, password=None, realm=None, ou=None): if username is None or password is None: return None @@ -1310,6 +1331,7 @@ class LDAPBackend(object): if conn is None: logger.warning(u'unable to synchronize with LDAP servers %s', force_text(block['url'])) continue + cls.check_group_to_role_mappings(block) user_basedn = force_text(block.get('user_basedn') or block['basedn']) user_filter = force_text(block['sync_ldap_users_filter'] or block['user_filter']) user_filter = user_filter.replace('%s', '*') diff --git a/tests/test_ldap.py b/tests/test_ldap.py index c02898a30..589e14924 100644 --- a/tests/test_ldap.py +++ b/tests/test_ldap.py @@ -511,7 +511,7 @@ def test_group_staff(slapd, settings, client, db): assert not response.context['user'].is_superuser -def test_get_users(slapd, settings, db, monkeypatch): +def test_get_users(slapd, settings, db, monkeypatch, caplog): import django.db.models.base from types import MethodType from django.contrib.auth.models import Group @@ -525,6 +525,9 @@ def test_get_users(slapd, settings, db, monkeypatch): [u'cn=group2,o=ôrga', ['Group2']], ], 'group_filter': '(&(memberUid={uid})(objectClass=posixGroup))', + 'group_to_role_mapping': [ + ['cn=unknown,o=dn', ['Role2']], + ] }] save = mock.Mock(wraps=ldap_backend.LDAPUser.save) bulk_create = mock.Mock(wraps=django.db.models.query.QuerySet.bulk_create) @@ -546,7 +549,8 @@ def test_get_users(slapd, settings, db, monkeypatch): # Check that if nothing changed no save() is made save.reset_mock() bulk_create.reset_mock() - users = list(ldap_backend.LDAPBackend.get_users()) + with utils.check_log(caplog, 'ldap: unknown group "cn=unknown,o=dn" mapped to a role'): + users = list(ldap_backend.LDAPBackend.get_users()) assert save.call_count == 0 assert bulk_create.call_count == 0