From e1c470239877327d3030246d8c4bd7549e8d9ede Mon Sep 17 00:00:00 2001 From: DanielBatteryStapler Date: Sat, 30 Jul 2022 10:05:10 -0400 Subject: [PATCH] implement LDAP as authentication backend support (#274) --- Dockerfile | 2 +- README.md | 12 ++++++++++++ docs/FAQ.md | 3 --- tubearchivist/config/settings.py | 29 +++++++++++++++++++++++++++++ tubearchivist/requirements.txt | 1 + 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0d09add..071da0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ FROM python:3.10.5-slim-bullseye AS builder ARG TARGETPLATFORM RUN apt-get update -RUN apt-get install -y --no-install-recommends build-essential gcc +RUN apt-get install -y --no-install-recommends build-essential gcc libldap2-dev libsasl2-dev libssl-dev # install requirements COPY ./tubearchivist/requirements.txt /requirements.txt diff --git a/README.md b/README.md index dd2c014..1a65628 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,18 @@ Should that not be an option, the Tube Archivist container takes these two addit Changing any of these two environment variables will change the files *nginx.conf* and *uwsgi.ini* at startup using `sed` in your container. +## LDAP Authentication +LDAP authentication is not yet available in *stable* builds but is implemented for *unstable*. It can be enabled and configured using the following environment variables: + + - `TA_LDAP` (ex: `true`) Set to anything besides empty string to use LDAP authentication instead of local user authentication. + - `TA_LDAP_SERVER_URI` (ex: `ldap://ldap-server:389`) Set to the uri of your LDAP server. + - `TA_LDAP_BIND_DN` (ex: `uid=search-user,ou=users,dc=your-server`) DN of the user that is able to perform searches on your LDAP account. + - `TA_LDAP_BIND_PASSWORD` (ex: `yoursecretpassword`) Password for the search user. + - `TA_LDAP_USER_BASE` (ex: `ou=users,dc=your-server`) Search base for user filter. + - `TA_LDAP_USER_FILTER` (ex: `(objectClass=user)`) Filter for valid users. Login usernames are automatically matched using `uid` and does not need to be specified in this filter. + +When LDAP authentication is enabled django passwords (e.g. the password defined in TA_PASSWORD) will not allow you to login, only the LDAP server is used. + ### Elasticsearch **Note**: Tube Archivist depends on Elasticsearch 8. diff --git a/docs/FAQ.md b/docs/FAQ.md index cec6a71..f3e4cc9 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -29,6 +29,3 @@ So Docker is the only supported installation method. If you don't have any exper ## 4. Finetuning Elasticsearch A minimal configuration of Elasticsearch (ES) is provided in the example docker-compose.yml file. ES is highly configurable and very interesting to learn more about. Refer to the [documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) if you want to get into it. - -## 5. Advanced Authentication -If you like to use things like SSO, LDAP or 2FA to login, consider using something like Authelia as a reverse proxy so this project can focus on the core task. Tube Archivist has a *remember me* checkbox at login to extend your sessions lifetime in your browser. diff --git a/tubearchivist/config/settings.py b/tubearchivist/config/settings.py index 569eed6..0fe904e 100644 --- a/tubearchivist/config/settings.py +++ b/tubearchivist/config/settings.py @@ -14,7 +14,9 @@ import hashlib from os import environ, path from pathlib import Path +import ldap from corsheaders.defaults import default_headers +from django_auth_ldap.config import LDAPSearch from home.src.ta.config import AppConfig # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -83,6 +85,33 @@ TEMPLATES = [ WSGI_APPLICATION = "config.wsgi.application" +if bool(environ.get("TA_LDAP")): + global AUTH_LDAP_SERVER_URI + AUTH_LDAP_SERVER_URI = environ.get("TA_LDAP_SERVER_URI") + + global AUTH_LDAP_BIND_DN + AUTH_LDAP_BIND_DN = environ.get("TA_LDAP_BIND_DN") + + global AUTH_LDAP_BIND_PASSWORD + AUTH_LDAP_BIND_PASSWORD = environ.get("TA_LDAP_BIND_PASSWORD") + + global AUTH_LDAP_USER_SEARCH + AUTH_LDAP_USER_SEARCH = LDAPSearch( + environ.get("TA_LDAP_USER_BASE"), + ldap.SCOPE_SUBTREE, + "(&(uid=%(user)s)" + environ.get("TA_LDAP_USER_FILTER") + ")", + ) + + global AUTH_LDAP_USER_ATTR_MAP + AUTH_LDAP_USER_ATTR_MAP = { + "username": "uid", + "first_name": "givenName", + "last_name": "sn", + "email": "mail", + } + + global AUTHENTICATION_BACKENDS + AUTHENTICATION_BACKENDS = ("django_auth_ldap.backend.LDAPBackend",) # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases diff --git a/tubearchivist/requirements.txt b/tubearchivist/requirements.txt index b07e8e4..ca8bc1d 100644 --- a/tubearchivist/requirements.txt +++ b/tubearchivist/requirements.txt @@ -10,3 +10,4 @@ ryd-client==0.0.3 uWSGI==2.0.20 whitenoise==6.2.0 yt_dlp==2022.7.18 +django-auth-ldap==4.1.0