zulip / zulip

Zulip server and web application. Open-source team chat that helps teams stay productive and focused.
https://zulip.com
Apache License 2.0
21.59k stars 7.85k forks source link

LDAP Authentication Issue #13565

Closed danielepesciallo closed 4 years ago

danielepesciallo commented 4 years ago

Hello Everybody, today i try to upgrade my Zulip Instance from 2.0.8 to 2.1.1.

After this, i'm not able to connect with my AD Credential. This is my setting.py file: `` AUTH_LDAP_SERVER_URI = "ldap://domain.name"

AUTH_LDAP_BIND_DN = "ldapzulip"

auth_ldap_bind_password

AUTH_LDAP_USERNAME_ATTR = 'uid' AUTH_LDAP_USER_SEARCH = LDAPSearch("ou=Users,dc=domain,dc=name", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)") AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("ou=Users,dc=domain,dc=name", ldap.SCOPE_SUBTREE, "(mail=%(email)s)")

LDAP_APPEND_DOMAIN = "domain.name" # type: Optional[str] LDAP_EMAIL_ATTR = "mail" # type: Optional[str] AUTH_LDAP_USER_ATTR_MAP = { "full_name": "displayName", "first_name": "givenName", "last_name": "sn", } ``

Can you help me?

Thanks, Daniele

mateuszmandera commented 4 years ago

@danielepesciallo You have both LDAP_APPEND_DOMAIN as well as AUTH_LDAP_REVERSE_EMAIL_SEARCH (and related), which aren't meant to go together. Which configuration type is the intended one? A, B or C? (See https://zulip.readthedocs.io/en/latest/production/authentication-methods.html#ldap-including-active-directory) Also, please the relevant error from the logs (probably in /var/log/zulip/errors.log)

danielepesciallo commented 4 years ago

Hi Mateusz, thanks for you reply! I want to connect to my Zulip Instance by username (not username@domain or email address). So, i used the B configuration.

Before the upgrade, i was able to connect without any problem; after this, i can't connect to my instance.

In /var/log/zulip/errors.log i can't see any auth error log.

What is the best "settings.py" file for connect Zulip 2.1.1 to my Active Directory? Thanks a lot!

Daniele

mateuszmandera commented 4 years ago

If you want LDAP_APPEND_DOMAIN mode, you should remove or comment out the reverse_email_search, username_attr and email_attr settings. Let me know if that fixes the issue. If it doesn't help, please try the query_ldap command (its mentioned in the doc i linked) to query for your username/email and post its output, it should tell us more about the problem.

-------- Original Message -------- On Dec 26, 2019, 01:05, Daniele Pesciallo wrote:

Hi Mateusz, thanks for you reply! I want to connect to my Zulip Instance by username (not username@domain or email address). So, i used the B configuration.

Before the upgrade, i was able to connect without any problem; after this, i can't connect to my instance.

In /var/log/zulip/errors.log i can't see any auth error log.

What is the best "settings.py" file for connect Zulip 2.1.1 to my Active Directory? Thanks a lot!

Daniele

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

danielepesciallo commented 4 years ago

Hi, i tried with your advice, but nothing. Now my "settings.py" is this: import ldap from django_auth_ldap.config import LDAPSearch

AUTH_LDAP_SERVER_URI = "ldap://domain.name" AUTH_LDAP_BIND_DN = "ldapzulip"

AUTH_LDAP_USER_SEARCH = LDAPSearch( "ou=Users,dc=domain,dc=name", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)" )

LDAP_APPEND_DOMAIN = "domain.name" # type: Optional[str]

AUTH_LDAP_USER_ATTR_MAP = { "full_name": "displayName", "first_name": "givenName", "last_name": "sn", }

I try with "query_ldap" command and this is the result: zulip@zulip:~$ /home/zulip/deployments/current/manage.py query_ldap pesciallo full_name: Pesciallo Daniele first_name: Daniele last_name: Pesciallo

Thanks, Daniele

mateuszmandera commented 4 years ago

@danielepesciallo That query_ldap output makes things seem like they're working :thinking: What exactly is the issue that's happening?

Can you also query_ldap for your email? (pesciallo@yourldapdomain rather than just pesciallo)

danielepesciallo commented 4 years ago

Yes, it's strange. I can't login in the web interface (Please enter a correct email and password. Note that both fields may be case-sensitive.) I tried the query_ldap command with pesciallo@doman and it works

zulip@zulip:~$ /home/zulip/deployments/current/manage.py query_ldap pesciallo@domain.name full_name: Pesciallo Daniele first_name: Daniele last_name: Pesciallo

On the web interface, i tried with email address d.pesciallo@domain.name, with Active Directory username pesciallo@domain.name and only with my sAMAccountName

Thanks

Daniele

mateuszmandera commented 4 years ago

Anything in /var/log/zulip/server.log? You could grep for ldap grep -i ldap /var/log/zulip/server.log Or just look at recent entries

danielepesciallo commented 4 years ago

There is nothing in /var/log/zulip/server.log that match with ldap (i tried with grep -i ldap /var/log/zulip/server.log)..

After that, i tried with tail -f /var/log/zulip/server ==> /var/log/zulip/server.log <== 2019-12-26 23:07:01.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:06.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:12.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:17.284 INFO [] Tornado 9993 0.0% busy over the past 59.0 seconds 2019-12-26 23:07:23.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:29.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:34.284 INFO [] Tornado 9993 0.0% busy over the past 59.0 seconds 2019-12-26 23:07:40.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds 2019-12-26 23:07:45.284 INFO [] Tornado 9993 0.0% busy over the past 60.0 seconds

mateuszmandera commented 4 years ago

Considering that query_ldap is succesfully finding you when querying for "pesciallo", I'm at a loss how logging in could be failing with that username if the correct password of the AD user is being given.

  1. Is the ZulipLDAPAuthBackend backend enabled in AUTHENTICATION_BACKENDS in /etc/zulip/settings.py?
  2. And is LDAP auth enabled for the realm? You can try in the django shell manage.py shell:
    from zproject.backends import ldap_auth_enabled
    ldap_auth_enabled(get_realm(""))

    (you may need to changed the argument to get_realm if the organization is on a subdomain)

danielepesciallo commented 4 years ago

Yes, the ZulipLDAPAuthBackend is enabled: Zulip_Authentication_Backend.txt

And this this is the LDAP auth: Zulip_LDAP_Answer.txt

mateuszmandera commented 4 years ago

Can you save this in zerver/management/commands/custom_command.py and run it manage.py custom_command?

from argparse import ArgumentParser
from typing import Any

from django.core.management.base import BaseCommand
from django.conf import settings

from zerver.models import get_user_by_delivery_email, get_realm
from zproject.backends import ZulipLDAPAuthBackend

class Command(BaseCommand):
    def handle(self, *args: Any, **options: str) -> None:
        realm = get_realm("")
        user = get_user_by_delivery_email('pesciallo@' + settings.LDAP_APPEND_DOMAIN, realm)
        print("User email: {} is_active: {}".format(user.email, user.is_active))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username='pesciallo', password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

(change your password of course)

danielepesciallo commented 4 years ago

This is the output CustomCommandOutput.txt

Thanks!

mateuszmandera commented 4 years ago

That makes it seem like the user pesciallo@yourldapdomain doesn't even exist in this realm? Can you run this version (I just added a print of the email for debugging and commented out the problematic attempt to fetch the user profile):

from argparse import ArgumentParser
from typing import Any

from django.core.management.base import BaseCommand
from django.conf import settings

from zerver.models import get_user_by_delivery_email, get_realm
from zproject.backends import ZulipLDAPAuthBackend

class Command(BaseCommand):
    def handle(self, *args: Any, **options: str) -> None:
        realm = get_realm("")
        print("Attempted email: " + 'pesciallo@' + settings.LDAP_APPEND_DOMAIN)
        #user = get_user_by_delivery_email('pesciallo@' + settings.LDAP_APPEND_DOMAIN, realm)
        #print("User email: {} is_active: {}".format(user.email, user.is_active))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username='pesciallo', password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

(again, the password needs to be set to the AD password)

danielepesciallo commented 4 years ago

My Domain Name is dn.ne (it's an example), so my username on the domain is pesciallo@dn.ne My Email address is @domain.name, for example, d.pesciallo@domain.name

I tried with your command and the result is "None" CustomCommandOutput.txt

With the previous version i was able to logged into Zulip only with "pesciallo". Thanks

mateuszmandera commented 4 years ago

Ah, that would explain the confusing results I think. So, let me check that I understand this correctly.

  1. Your sAMAccountName is pesciallo?
  2. The domain name is dn.ne (so it doesn't actually match the email address domain?)?
  3. And your zulip account's email is d.pesciallo@domain.name? Is this the value of the mail attribute of your account's entry in AD?

If this is (close to) correct, then a different configuration type will be needed then config (B) with LDAP_APPEND_DOMAIN and that'll explain our issues. Once you clarify these questions, we should be able to figure out the right config.

Zulip 2.0.x had a bunch of bugs (or missing functionality) regarding handling of email in ldap (especially in configurations with both EmailAuthBackend and ZulipLDAPAuthBackend), so it's quite likely that the reason things worked before was the result of some unintended effect of the issues in the old ldap system - a case of a bug becoming a feature :smile:

danielepesciallo commented 4 years ago

Correctly, My sAMAccountName is pesciallo, my Domain Name is dn.ne and the value of my mail is in the mail attribute of my AD account :smile:

Zulip 2.0.x had a bunch of bugs (or missing functionality) regarding handling of email in ldap (especially in configurations with both EmailAuthBackend and ZulipLDAPAuthBackend), so it's quite likely that the reason things worked before was the result of some unintended effect of the issues in the old ldap system - a case of a bug becoming a feature smile

Ah ok :smile: , good :smiley:

mateuszmandera commented 4 years ago

Okay, let's try:

  1. Set LDAP_APPEND_DOMAIN = None
  2. AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("ou=Users,dc=domain,dc=name",
                                   ldap.SCOPE_SUBTREE, "(mail=%(email)s)")

    (I'm not sure if the dc values should be exactly this - but they should match what you have in AUTH_LDAP_USER_SEARCH, because you have that one correctly configured)

  3. AUTH_LDAP_USERNAME_ATTR = "sAMAccountName"
  4. LDAP_EMAIL_ATTR = "mail"

I'm assuming mail is correct name of the attribute that has email addresses of users in AD.

mateuszmandera commented 4 years ago

For verification, query_ldap should correctly find your AD info in both cases of querying with your sAMAccountName value or your email address.

mateuszmandera commented 4 years ago

Did you restart the server after changing settings? Are you getting the same error still when trying to log in? And can you check server.log and errors.log again?

"username": "sAMAccountName", shouldn't be in AUTH_LDAP_USER_ATTR_MAP I think

mateuszmandera commented 4 years ago

In addition to the previous question, did you perhaps change email visibility settings for the organization? We had a bug there that's now fixed.

danielepesciallo commented 4 years ago

Hi, so, i removed "username": "sAMAccountName" and i've added AUTH_LDAP_USERNAME_ATTR = "sAMAccountName".

After that, i restarted the server (su zulip -c '/home/zulip/deployments/last/scripts/restart-server')

Now, on the server.log, i see this error when i try to log in:

2019-12-28 22:22:53.904 INFO [zr] 172.17.36.24 POST 200 53ms (db: 4ms/3q) /accounts/login/ (unauth via ?)

In addition to the previous question, did you perhaps change email visibility settings for the organization? We had a bug there that's now fixed.

About zulip settings? I don't think I changed this setting

Thanks, Daniele

mateuszmandera commented 4 years ago

Can you try this command with the current settings:

from argparse import ArgumentParser
from typing import Any

from django.core.management.base import BaseCommand
from django.conf import settings

from zerver.models import get_user_by_delivery_email, get_realm
from zproject.backends import ZulipLDAPAuthBackend

class Command(BaseCommand):
    def handle(self, *args: Any, **options: str) -> None:
        realm = get_realm("")
        email = "youremail@domain"
        print("Attempted email: " + email)
        user = get_user_by_delivery_email(email, realm)
        print("User email: {} is_active: {}".format(user.email, user.is_active))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username='pesciallo', password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username=email, password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

setting the password an email values correctly. The email should be your email in AD (so it should match the mail attribute of your AD entry).

Same way as before, save it in zerver/management/commands/custom_command.py and run manage.py custom_command.

rushikesh90 commented 4 years ago

Just for suggestion, if you have access to AD, try getting wireshark traces. It might help if any wrong query is being sent.

danielepesciallo commented 4 years ago

import

Can you try this command with the current settings:

from argparse import ArgumentParser
from typing import Any

from django.core.management.base import BaseCommand
from django.conf import settings

from zerver.models import get_user_by_delivery_email, get_realm
from zproject.backends import ZulipLDAPAuthBackend

class Command(BaseCommand):
    def handle(self, *args: Any, **options: str) -> None:
        realm = get_realm("")
        email = "youremail@domain"
        print("Attempted email: " + email)
        user = get_user_by_delivery_email(email, realm)
        print("User email: {} is_active: {}".format(user.email, user.is_active))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username='pesciallo', password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

        return_data = {}
        result = ZulipLDAPAuthBackend().authenticate(username=email, password='yourpassword',
                                            realm=realm, return_data=return_data)
        print("result: {}\nreturn_data:{}".format(result, return_data))

setting the password an email values correctly. The email should be your email in AD (so it should match the mail attribute of your AD entry).

Same way as before, save it in zerver/management/commands/custom_command.py and run manage.py custom_command.

Hi Mateusz, this is the output:

zulip@zulip:~$ /home/zulip/deployments/current/manage.py custom_command Attempted email: d.pesciallo@domain.name User email: d.pesciallo@domain.name is_active: False result: None return_data:{} result: None return_data:{}

Thanks!

mateuszmandera commented 4 years ago

@danielepesciallo Your user account is deactivated for some reason - my guess would be that you have syncing with LDAP set up? Because with the ldap configuration causing failure to find the account in AD, syncing would have deactivated it. In that case, all other user accounts probably got deactivated. But this is very easy to fix.

First you can reactivate yourself and confirm that you can log in now. If it works you can either reactivate the users by clicking manually in the UI (in Users section in organization settings) or let me know if you need help automating the process (if you have too many users that got deactivated to click through them all in reasonable time).

To reactivate yourself, run in manage.py shell:

  1. from zerver.lib.actions import do_reactivate_user
  2. do_reactivate_user(get_user_by_delivery_email("your_email@domain.com", get_realm("")))
danielepesciallo commented 4 years ago

Yes, now it works! I'm able to connect with my AD account!

Thanks for all!! :smile:

mateuszmandera commented 4 years ago

Great news!

Summary for anyone looking through the issue in the future - the problem was some misconfiguration of the ldap settings, which just required fixing and then a bit extra cleanup to reactivate user accounts that got deactivated by ldap sync due to not finding the corresponding accounts in AD>

@danielepesciallo @timabbott Can one of you close the issue?

timabbott commented 4 years ago

Also worth noting that we added e81aa740bc57c2bb5ec124ed0e37d79ef7da47c2 to avoid that category of misconfiguration resulting in every user being deactivated.

smerchla commented 9 months ago

Please help me too. LDAP not working. This is a my config. AUTH_LDAP_SERVER_URI = "172.16.16.10" - AD server AUTH_LDAP_BIND_DN = "ldap" - my ldap user in the AD. AUTH_LDAP_USER_SEARCH = LDAPSearch( "OU=Staff,OU=Users and Groups,DC=XXX,DC=local", ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)" LDAP_APPEND_DOMAIN = "mydomain.com" LDAP_EMAIL_ATTR = "mail" AUTH_LDAP_REVERSE_EMAIL_SEARCH = LDAPSearch("OU=IT,OU=Staff,OU=Users and Groups,DC=XXX,DC=local",ldap.SCOPE_SUBTREE, "(mail=%(email)s)") AUTH_LDAP_USERNAME_ATTR = "sAMAccountName"

mateuszmandera commented 9 months ago

@smerchla Can you post in chat.zulip.org #production help stream?

If your users are supposed to login with their samaccountname value and email is be read from the mail attribute, then most likely you just need to set LDAP_APPEND_DOMAIN to None.

LDAP_APPEND_DOMAIN is in conflict with these other settings

smerchla commented 9 months ago

@smerchla Can you post in chat.zulip.org #production help stream?

If your users are supposed to login with their samaccountname value and email is be read from the mail attribute, then most likely you just need to set LDAP_APPEND_DOMAIN to None.

LDAP_APPEND_DOMAIN is in conflict with these other settings

Thanks, but it didn't work