Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDAP authentication over SSL issue #24

Closed
Pbast opened this issue Mar 15, 2019 · 13 comments
Closed

LDAP authentication over SSL issue #24

Pbast opened this issue Mar 15, 2019 · 13 comments
Assignees
Labels
bug Something isn't working

Comments

@Pbast
Copy link

Pbast commented Mar 15, 2019

Hello,

I try to use your nice LDAP crontrib on my taiga but my LDAP authentication failed on my LDAPs server...
I can not test authentication without TLS.
I already use some application to authenticate on our ldaps but I'm newbie on taiga and I didn't found a way to displayed logs.
(Launch tiga with "python manage.py runserver" doesn't displayed any logs about my LDAPs authentication.

Could you tell me how I can debug my ldap authentication ?

On my java application, to use ldaps authneticate I have a certicate file to import in my jvm keystore. Do I need to use a similar way (I don't know how)?

Thxs for any help, tell me if I didn't use the good way to ask some help about your ldap extension.

Here my taiga-back/settings/local.py file:

INSTALLED_APPS += ["taiga_contrib_ldap_auth_ext"]

# TODO https://github.com/Monogramm/taiga-contrib-ldap-auth-ext/issues/16
LDAP_SERVER = 'ldap://ldap.xxxx.fr'
LDAP_PORT = yyy

# Flag to enable LDAP with STARTTLS before bind
LDAP_START_TLS = True

# Support of alternative LDAP ciphersuites
from ldap3 import Tls
import ssl

LDAP_TLS_CERTS = Tls(validate=ssl.CERT_NONE, version=ssl.PROTOCOL_TLSv1, ciphers='RSA+3DES')

# Full DN of the service account use to connect to LDAP server and search for login user's account entry
# If LDAP_BIND_DN is not specified, or is blank, then an anonymous bind is attempated
# LDAP_BIND_DN = 'CN=SVC Account,OU=Service Accounts,OU=Servers,DC=example,DC=com'
# LDAP_BIND_PASSWORD = '<REPLACE_ME>'
LDAP_BIND_DN = ''
LDAP_BIND_PASSWORD = ''
# Additional search criteria to the filter (will be ANDed)
#LDAP_SEARCH_FILTER_ADDITIONAL = '(mail=*)'

# Names of attributes to get username, e-mail and full name values from
# These fields need to have a value in LDAP 
LDAP_USERNAME_ATTRIBUTE = 'zzz'
LDAP_EMAIL_ATTRIBUTE = 'zzzzz'
LDAP_FULL_NAME_ATTRIBUTE = 'zzzzz'

Pascal B

@Pbast Pbast added the bug Something isn't working label Mar 15, 2019
@madmath03
Copy link
Member

madmath03 commented Mar 16, 2019

Hello,

First, what is the version of the plugin you are using ?
Version 0.3.4 is stable but the versions between 0.4.0 and 0.4.2 had a bug on registration and should be upgraded to 0.4.3 that I just released. If you are using 0.4.x, I suggest you upgrade first then test again.

Regarding debug, first thing to look at is your JavaScript Console and Network to check the API results.
If you're using Chrome or Firefox, use F12 to display development console and see in the Network what's the API result when you try to log in.
If you see an internal error, you should normally find a stack trace about that error in your backend logs, but if the API does not answer with something like "Internal error", but simply "LDAP login ...", it's probably due to a configuration error and there isn't much to help you debug it...

Regarding LDAPS connection, you only need to import a certificate in a JVM keystore if it's a self-signed (or invalid) certificate so I'm assuming this is the situation you are in.
Here, I guess you would need to disable certificate verification but that's not a use case I've tried before so I'm not too sure how to do it...
I think you will need to find how to configure ldap3 to not crash if certificate is not valid but I couldn't find exactly how to do it. You will probably need to edit directly the plugin's connector.py and test different options for creating the Server and Connection object.

If you do manage to find out the proper configuration for self-signed certificates, you can then share it here or send a Pull Request with a property to enable it on request.

Hope that will help you.

@Pbast
Copy link
Author

Pbast commented Mar 18, 2019

Hello,
JS console displayed: {"error_message": "Error connecting to LDAP server: ('unable to open socket', [(LDAPSocketOpenError("('socket ssl wrapping error: [SSL: NO_CIPHERS_AVAILABLE] no ciphers available (_ssl.c:720)',)",), ('xx.xx.xx.xx', xxx))])"}

I could not disable ldap certificate verification (because I'm not the ldap administrator).
I have ldap certificate but I don't know how to import it manually in your extension.
I copy/paste certificate in /etc/ssl/certs/ directory (on my debian) because

if you leave all these parameter to None the SSLContext will use the system wide certificate store (ssl path on linux, CA stores on Windows)
from https://ldap3.readthedocs.io/ssltls.html#sslcontext

Thxs

@Pbast Pbast changed the title LDAP authentication over TLS issue LDAP authentication over SSL issue Mar 18, 2019
@Pbast
Copy link
Author

Pbast commented Mar 18, 2019

Note: I didn't use TLS. I use ldaps.
I have this error message now:

{"error_message": "Error connecting to LDAP server: ('unable to open socket', [(LDAPSocketOpenError("('socket ssl wrapping error: [SSL] PEM lib (_ssl.c:2964)',)",), ('xxxxxxxxx))])"}

@madmath03
Copy link
Member

madmath03 commented Mar 18, 2019

Well, when I said "disable ldap certificate verification", I meant on the taiga-contrib-ldap-auth-ext side, not on the LDAP server side but the validate=ssl.CERT_NONE in your Tls object so we can skip that.

Here the errors you have seems to come from the client side (taiga-contrib-ldap-auth-ext) which refuses to open a secure connection with your LDAP server.

The "no ciphers available" error makes me think that maybe your environment is not properly setup and the SSL ciphers needed to encrypt your connection are missing. Do you have openssl installed ? Does python has access to them ?

Also, take a look at this issue : cannatag/ldap3#242
The error mentioned looks a lot like your error with TLS and since this is the library we are using for opening LDAP connection, you might find some clues of what's wrong with your setup.

By the way, for such error messages in the JS console, you should see a similar stack trace in your taiga backend output.

@Pbast
Copy link
Author

Pbast commented Mar 18, 2019

Well, when I said "disable ldap certificate verification", I meant on the taiga-contrib-ldap-auth-ext side, not on the LDAP server side but the validate=ssl.CERT_NONE in your Tls object so we can skip that.

With validate=ssl.CERT_NONE I have error 500: Internal server error

The "no ciphers available" error makes me think that maybe your environment is not properly setup and the SSL ciphers needed to encrypt your connection are missing. Do you have openssl installed ? Does python has access to them ?

Yes i have openssl. Probably python has access to them (I used debian repository). I don't know how to check it.

Also, take a look at this issue : cannatag/ldap3#242
The error mentioned looks a lot like your error with TLS and since this is the library we are using for opening LDAP connection, you might find some clues of what's wrong with your setup.

I read ldap3 doc, but these settings doesn't work:

# LDAP_TLS_CERTS = Tls(validate=ssl.CERT_OPTIONAL, version=ssl.PROTOCOL_SSLv23, ca_certs_file='/etc/certs/MyCert.pem')
#LDAP_TLS_CERTS = Tls(validate=ssl.CERT_REQUIRED, version=ssl.PROTOCOL_SSLv23, ca_certs_file='/etc/certs/Mycert.pem')
LDAP_TLS_CERTS = Tls(validate=ssl.CERT_NONE)

By the way, for such error messages in the JS console, you should see a similar stack trace in your taiga backend output.

Anyway, it's my main issue, I don't know how to log errors. I didn't know python/django/ stuff...
It's shame, taiga doc didn't show how to debug.

@madmath03
Copy link
Member

With validate=ssl.CERT_NONE I have error 500: Internal server error

That's definitely an interesting information because that's basically what should work for you and we need to find what's this internal error.

Anyway, it's my main issue, I don't know how to log errors. I didn't know python/django/ stuff...
It's shame, taiga doc didn't show how to debug.

Well, I'm not really used to python/django either, but from what I looked up regarding Taiga, there are properties available to enable debug for both backend and frontend. Take a look at the example configuration:

Also, as mentioned in one of Taiga issues (https://github.com/taigaio/taiga-back/issues/1009), you should normally be able to see your errors in the shell with which you started taiga backend server.
If you still cannot retrieve your logs, we will both be stuck so I suggest you open a new issue on Taiga repository to ask for help on how to retrieve your logs.

Once you manage to retrieve them, we can try to look what's wrong with your ldap configuration.

@Pbast
Copy link
Author

Pbast commented Mar 20, 2019

Ok I managed to log LDAP authentication like this way:

  • execute this command on taiga server:
    python manage.py runserver taiga.domaine.fr:8000
  • on another machine l execute POST authentication request to taiga backend and I send result in html file:
    curl -H "Content-Type: application/json" -d '{"type": "ldap", "username": "prenom.nom, "password": "MyNicePassword"}' http://taiga.domaine.fr:8000/api/v1/auth>test.html

Then with LDAP account authentication, the console output is

ERROR:2019-03-20 09:37:23,974: Internal Server Error: /api/v1/auth
Traceback (most recent call last):
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/taiga/taiga-back/taiga/base/api/viewsets.py", line 106, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/taiga/taiga-back/taiga/base/api/views.py", line 460, in dispatch
    response = self.handle_exception(exc)
  File "/home/taiga/taiga-back/taiga/base/api/views.py", line 458, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/taiga/taiga-back/taiga/auth/api.py", line 113, in create
    data = auth_plugins[login_type]['login_func'](request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py", line 76, in ldap_login_func
    user = register_or_update(username = username, email = email, full_name = full_name, password = password_input)
  File "/usr/lib/python3.5/contextlib.py", line 30, in inner
    return func(*args, **kwds)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py", line 104, in register_or_update
    superuser = false
NameError: name 'false' is not defined
[20/Mar/2019 09:37:24] "POST /api/v1/auth HTTP/1.1" 500 118316

When authenticate with a local account, console displayed:

[20/Mar/2019 09:38:46] "POST /api/v1/auth HTTP/1.1" 200 793

Here html file return from curl command: https://pastebin.com/t7VY4B0Z that you can paste in html file and open in a browser.
Like you can see taiga can read LDAP information (I get ldap user email and fullname)

Thxs.
Pascal

@Pbast
Copy link
Author

Pbast commented Mar 20, 2019

I replace superuser = false with superuser = False in "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py" but now I have this error displayed:

ERROR:2019-03-20 10:07:32,026: Internal Server Error: /api/v1/auth
Traceback (most recent call last):
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py", line 108, in register_or_update
    user = user_model.objects.get(username = username_unique)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/db/models/query.py", line 380, in get
    self.model._meta.object_name
taiga.users.models.DoesNotExist: User matching query does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/taiga/taiga-back/taiga/base/api/viewsets.py", line 106, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/taiga/taiga-back/taiga/base/api/views.py", line 460, in dispatch
    response = self.handle_exception(exc)
  File "/home/taiga/taiga-back/taiga/base/api/views.py", line 458, in dispatch
    response = handler(request, *args, **kwargs)
  File "/home/taiga/taiga-back/taiga/auth/api.py", line 113, in create
    data = auth_plugins[login_type]['login_func'](request)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py", line 76, in ldap_login_func
    user = register_or_update(username = username, email = email, full_name = full_name, password = password_input)
  File "/usr/lib/python3.5/contextlib.py", line 30, in inner
    return func(*args, **kwds)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/taiga_contrib_ldap_auth_ext/services.py", line 115, in register_or_update
    is_superuser = superuser)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/db/models/query.py", line 392, in create
    obj = self.model(**kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/contrib/auth/base_user.py", line 68, in __init__
    super(AbstractBaseUser, self).__init__(*args, **kwargs)
  File "/home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages/django/db/models/base.py", line 573, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'is_staff' is an invalid keyword argument for this function
[20/Mar/2019 10:07:32] "POST /api/v1/auth HTTP/1.1" 500 153091

@madmath03
Copy link
Member

Okay...
Well, the superuser error is pretty much the first thing I told you:

First, what is the version of the plugin you are using ?
Version 0.3.4 is stable but the versions between 0.4.0 and 0.4.2 had a bug on registration and should be upgraded to 0.4.3 that I just released. If you are using 0.4.x, I suggest you upgrade first then test again.

The is_staff error is also something I fixed, so please, upgrade your plugin to the latest version.

@Pbast
Copy link
Author

Pbast commented Mar 20, 2019

When you told me to upgrade, I did ,but now I don't know if I did well...
I execute this command, and it seem I use taiga-contrib-ldap-auth-ext 0.4.5 version?
Maybe I use the wrong command to upgrade? WDYT?

(taiga) taiga@MyServer:~/taiga-back$ pip install taiga-contrib-ldap-auth-ext
Requirement already satisfied: taiga-contrib-ldap-auth-ext in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (0.4.1)
Requirement already satisfied: django>=1.7 in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (from taiga-contrib-ldap-auth-ext) (1.11.16)
Requirement already satisfied: ldap3>=0.9.8.4 in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (from taiga-contrib-ldap-auth-ext) (2.5.2)
Requirement already satisfied: pytz in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (from django>=1.7->taiga-contrib-ldap-auth-ext) (2018.7)
Requirement already satisfied: pyasn1>=0.1.8 in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (from ldap3>=0.9.8.4->taiga-contrib-ldap-auth-ext) (0.4.5)

@madmath03
Copy link
Member

madmath03 commented Mar 20, 2019

The latest version is 0.4.3. Version 0.4.5 does not exist, or at least not yet.
The version you have installed is mentioned in the first line : 0.4.1

Requirement already satisfied: taiga-contrib-ldap-auth-ext in /home/taiga/.virtualenvs/taiga/lib/python3.5/site-packages (0.4.1)

To upgrade your package, use

pip install --upgrade taiga-contrib-ldap-auth-ext

or in short

pip install -U taiga-contrib-ldap-auth-ext

See Python documentation for details.

@Pbast
Copy link
Author

Pbast commented Mar 20, 2019

\o/ thxs authentication ldap working well now.
Sorry about the noise :-/
Last thing, could you tell me if the password of ldap account is store in DB (I hope it is not, because our politics security)?

@madmath03
Copy link
Member

madmath03 commented Mar 20, 2019

Glad it's finally working for you 👍

Regarding the LDAP passwords, they are saved in Taiga Database since release 0.4 (see release note).
This was needed to allow LDAP users to login to the Taiga admin console (reported in #17 and #21).

I do not know your security policies, but you should know that even if the passwords are stored in the database, they are always hashed and never stored as clear text (thanks to Django and Taiga security policies).
If you really do not want the passwords stored in the DB even if hashed, you should either need to rollback to release 0.3.4, or create a feature request and wait for a future release that would allow you to disable it (you can even send a PR with the code for this feature 😉).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants