From 3daec7783a812dfacb2da341c1400339bdb7967f Mon Sep 17 00:00:00 2001 From: Mateusz Mandera Date: Thu, 7 Nov 2019 06:57:09 +0100 Subject: [PATCH] ldap: Fix development environment configuration. The state of the FAKELDAP setup for the dev env has fallen behind the backend changes and updates to fakeldap (which implemented SCOPE_ONELEVEL searches), as well as having some other minor issues. This commit restore it to a working state and now all three config modes work properly. --- zerver/lib/dev_ldap_directory.py | 5 ++++- zerver/tests/test_auth_backends.py | 17 ++++++++++------- zproject/dev_settings.py | 15 ++++++++++----- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/zerver/lib/dev_ldap_directory.py b/zerver/lib/dev_ldap_directory.py index 8eeca2e827..20573fc29f 100644 --- a/zerver/lib/dev_ldap_directory.py +++ b/zerver/lib/dev_ldap_directory.py @@ -35,16 +35,19 @@ def generate_dev_ldap_dir(mode: str, num_users: int=8) -> Dict[str, Dict[str, An } if mode == 'a': ldap_dir['uid=' + email + ',ou=users,dc=zulip,dc=com'] = dict( + uid=[email, ], thumbnailPhoto=[profile_images[i % len(profile_images)], ], userAccountControl=[LDAP_USER_ACCOUNT_CONTROL_NORMAL, ], **common_data) elif mode == 'b': ldap_dir['uid=' + email_username + ',ou=users,dc=zulip,dc=com'] = dict( + uid=[email_username, ], jpegPhoto=[profile_images[i % len(profile_images)], ], **common_data) elif mode == 'c': ldap_dir['uid=' + email_username + ',ou=users,dc=zulip,dc=com'] = dict( - email=email, + uid=[email_username, ], + email=[email, ], **common_data) return ldap_dir diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index b152345c0a..032ef8b015 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -2526,31 +2526,34 @@ class TestLDAP(ZulipLDAPTestCase): common_attrs = ['cn', 'userPassword', 'phoneNumber', 'birthDate'] for key, value in ldap_dir.items(): self.assertTrue(regex.match(key)) - self.assertCountEqual(list(value.keys()), common_attrs + ['thumbnailPhoto', 'userAccountControl']) + self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'thumbnailPhoto', 'userAccountControl']) ldap_dir = generate_dev_ldap_dir('b', 9) self.assertEqual(len(ldap_dir), 9) regex = re.compile(r'(uid\=)+[a-zA-Z0-9_.+-]+(\,ou\=users\,dc\=zulip\,dc\=com)') for key, value in ldap_dir.items(): self.assertTrue(regex.match(key)) - self.assertCountEqual(list(value.keys()), common_attrs + ['jpegPhoto']) + self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'jpegPhoto']) ldap_dir = generate_dev_ldap_dir('c', 8) self.assertEqual(len(ldap_dir), 8) regex = re.compile(r'(uid\=)+[a-zA-Z0-9_.+-]+(\,ou\=users\,dc\=zulip\,dc\=com)') for key, value in ldap_dir.items(): self.assertTrue(regex.match(key)) - self.assertCountEqual(list(value.keys()), common_attrs + ['email']) + self.assertCountEqual(list(value.keys()), common_attrs + ['uid', 'email']) @override_settings(AUTHENTICATION_BACKENDS=('zproject.backends.ZulipLDAPAuthBackend',)) - def test_dev_ldap_fail_login(self) -> None: # nocoverage + def test_dev_ldap_fail_login(self) -> None: # Tests that login with a substring of password fails. We had a bug in # dev LDAP environment that allowed login via password substrings. self.mock_ldap.directory = generate_dev_ldap_dir('B', 8) with self.settings( - LDAP_APPEND_DOMAIN='zulip.com', - AUTH_LDAP_BIND_PASSWORD='', - AUTH_LDAP_USER_DN_TEMPLATE='uid=%(user)s,ou=users,dc=zulip,dc=com'): + AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", + ldap.SCOPE_ONELEVEL, "(uid=%(user)s)"), + AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", + ldap.SCOPE_ONELEVEL, "(email=%(email)s)"), + LDAP_APPEND_DOMAIN='zulip.com' + ): user_profile = self.backend.authenticate(username='ldapuser1', password='dapu', realm=get_realm('zulip')) diff --git a/zproject/dev_settings.py b/zproject/dev_settings.py index 69df17cb59..8c9285e977 100644 --- a/zproject/dev_settings.py +++ b/zproject/dev_settings.py @@ -109,16 +109,20 @@ FAKE_LDAP_MODE = None # type: Optional[str] # FAKE_LDAP_NUM_USERS = 8 if FAKE_LDAP_MODE: + import ldap + from django_auth_ldap.config import LDAPSearch # To understand these parameters, read the docs in # prod_settings_template.py and on ReadTheDocs. LDAP_APPEND_DOMAIN = None - AUTH_LDAP_USER_DN_TEMPLATE = 'uid=%(user)s,ou=users,dc=zulip,dc=com' + AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", + ldap.SCOPE_ONELEVEL, "(uid=%(user)s)") + AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", + ldap.SCOPE_ONELEVEL, "(email=%(email)s)") if FAKE_LDAP_MODE == 'a': - import ldap - from django_auth_ldap.config import LDAPSearch - AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", - ldap.SCOPE_SUBTREE, "(email=%(user)s)") + AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("ou=users,dc=zulip,dc=com", + ldap.SCOPE_ONELEVEL, "(uid=%(email)s)") + AUTH_LDAP_USERNAME_ATTR = "uid" AUTH_LDAP_USER_ATTR_MAP = { "full_name": "cn", "avatar": "thumbnailPhoto", @@ -136,6 +140,7 @@ if FAKE_LDAP_MODE: "custom_profile_field__phone_number": "phoneNumber", } elif FAKE_LDAP_MODE == 'c': + AUTH_LDAP_USERNAME_ATTR = "uid" LDAP_EMAIL_ATTR = 'email' AUTH_LDAP_USER_ATTR_MAP = { "full_name": "cn",