ldap: Add a setting to automatically deactivate non_matching users.

Fixes: #11151.
This commit is contained in:
Harshit Bansal
2019-01-13 12:53:52 +00:00
committed by Tim Abbott
parent 6797dea6c3
commit 71761bc2da
6 changed files with 42 additions and 1 deletions

View File

@@ -179,6 +179,18 @@ This feature works by checking for the `ACCOUNTDISABLE` flag on the
[this handy resource](https://jackstromberg.com/2013/01/useraccountcontrol-attributeflag-values/) [this handy resource](https://jackstromberg.com/2013/01/useraccountcontrol-attributeflag-values/)
for details on the various `userAccountControl` flags. for details on the various `userAccountControl` flags.
#### Deactivating non-matching users
Starting with Zulip 2.0, Zulip supports automatically deactivating
users if they are not found by the `AUTH_LDAP_USER_SEARCH` query
(either because the user is no longer in LDAP/Active Directory, or
because the user no longer matches the query). This feature is
enabled by default if LDAP is the only authentication backend
configured on the Zulip server. Otherwise, you can enable this
feature by setting `LDAP_DEACTIVATE_NON_MATCHING_USERS` to `True` in
`/etc/zulip/settings.py`. Nonmatching users will be fully deactivated
the next time your `manage.py sync_ldap_user_data` cron job runs.
#### Other fields #### Other fields
Other fields you may want to sync from LDAP include: Other fields you may want to sync from LDAP include:

View File

@@ -28,6 +28,8 @@ def sync_ldap_user_data(user_profiles: List[UserProfile]) -> None:
logger.info("Updated %s." % (u.email,)) logger.info("Updated %s." % (u.email,))
else: else:
logger.warning("Did not find %s in LDAP." % (u.email,)) logger.warning("Did not find %s in LDAP." % (u.email,))
if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS:
logger.info("Deactivated non-matching user: %s" % (u.email,))
except ZulipLDAPException as e: except ZulipLDAPException as e:
logger.error("Error attempting to update user %s:" % (u.email,)) logger.error("Error attempting to update user %s:" % (u.email,))
logger.error(e) logger.error(e)

View File

@@ -2587,6 +2587,19 @@ class TestZulipLDAPUserPopulator(ZulipLDAPTestCase):
hamlet = self.example_user('hamlet') hamlet = self.example_user('hamlet')
self.assertEqual(hamlet.avatar_source, UserProfile.AVATAR_FROM_USER) self.assertEqual(hamlet.avatar_source, UserProfile.AVATAR_FROM_USER)
def test_deactivate_non_matching_users(self) -> None:
self.mock_ldap.directory = {}
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',
LDAP_DEACTIVATE_NON_MATCHING_USERS=True):
result = sync_user_from_ldap(self.example_user('hamlet'))
self.assertFalse(result)
hamlet = self.example_user('hamlet')
self.assertFalse(hamlet.is_active)
class TestZulipAuthMixin(ZulipTestCase): class TestZulipAuthMixin(ZulipTestCase):
def test_get_user(self) -> None: def test_get_user(self) -> None:
backend = ZulipAuthMixin() backend = ZulipAuthMixin()

View File

@@ -443,7 +443,11 @@ class ZulipLDAPUserPopulator(ZulipLDAPAuthBackendBase):
def sync_user_from_ldap(user_profile: UserProfile) -> bool: def sync_user_from_ldap(user_profile: UserProfile) -> bool:
backend = ZulipLDAPUserPopulator() backend = ZulipLDAPUserPopulator()
updated_user = backend.populate_user(backend.django_to_ldap_username(user_profile.email)) updated_user = backend.populate_user(backend.django_to_ldap_username(user_profile.email))
return updated_user is not None if not updated_user:
if settings.LDAP_DEACTIVATE_NON_MATCHING_USERS:
do_deactivate_user(user_profile)
return False
return True
class DevAuthBackend(ZulipAuthMixin): class DevAuthBackend(ZulipAuthMixin):
# Allow logging in as any user without a password. # Allow logging in as any user without a password.

View File

@@ -478,6 +478,11 @@ AUTH_LDAP_USER_ATTR_MAP = {
# "userAccountControl": "userAccountControl", # "userAccountControl": "userAccountControl",
} }
# Whether to automatically deactivate users not found in LDAP. If LDAP
# is the only authentication method, then this setting defaults to
# True. If other authentication methods are enabled, it defaults to
# False.
#LDAP_DEACTIVATE_NON_MATCHING_USERS = True
################ ################
# Miscellaneous settings. # Miscellaneous settings.

View File

@@ -1297,6 +1297,11 @@ ZULIP_IOS_APP_ID = 'org.zulip.Zulip'
USING_APACHE_SSO = ('zproject.backends.ZulipRemoteUserBackend' in AUTHENTICATION_BACKENDS) USING_APACHE_SSO = ('zproject.backends.ZulipRemoteUserBackend' in AUTHENTICATION_BACKENDS)
if 'LDAP_DEACTIVATE_NON_MATCHING_USERS' not in vars():
LDAP_DEACTIVATE_NON_MATCHING_USERS = (
len(AUTHENTICATION_BACKENDS) == 1 and (AUTHENTICATION_BACKENDS[0] ==
"zproject.backends.ZulipLDAPAuthBackend"))
if len(AUTHENTICATION_BACKENDS) == 1 and (AUTHENTICATION_BACKENDS[0] == if len(AUTHENTICATION_BACKENDS) == 1 and (AUTHENTICATION_BACKENDS[0] ==
"zproject.backends.ZulipRemoteUserBackend"): "zproject.backends.ZulipRemoteUserBackend"):
HOME_NOT_LOGGED_IN = "/accounts/login/sso/" HOME_NOT_LOGGED_IN = "/accounts/login/sso/"