:snake: :alembic: Extended Taiga plugin for LDAP authentication
Extended Taiga.io plugin for LDAP authentication.
This is a fork of ensky/taiga-contrib-ldap-auth, which also retrieves the various contributions and other forks into one.
If you installed a dockerized Taiga using the 30 Minute Setup approach, you should be able to install this plugin using this guide.
The following will assume that you have a clone of the kaleidos-ventures/taiga-docker repository on the computer you want to host Taiga on.
taiga-back
taiga-back
section in the docker-compose.yml
: Replace image: taigaio/taiga-back:latest
with build: ./custom-back
custom-back
next to the docker-compose.yml
fileconfig.append.py
. Copy the contents of the taiga-back
configuration section from this document into it.Dockerfile
. The contents of the file are collapsed below.If you were to start Taiga now, it would not pull the taiga-back
directly from Docker Hub but instead build the image from the specified Dockerfile
. This is exactly what we want, however, do not start Taiga yet – there is still work to be done in taiga-front
.
custom-back/Dockerfile
Dockerfile
FROM taigaio/taiga-back:latest
# Insert custom configuration into the taiga configuration file
COPY config.append.py /taiga-back/settings
RUN cat /taiga-back/settings/config.append.py >> /taiga-back/settings/config.py && rm /taiga-back/settings/config.append.py
RUN pip install taiga-contrib-ldap-auth-ext
FROM ...
bases the image we build on the official taigaio/taiga-back
image.COPY ...
and RUN ...
copy the config.append.py
file into the container, append it to /taiga-back/settings/config.py
and then delete it again.RUN pip install ...
installs this plugin.taiga-front
Edit the taiga-front
section in the docker-compose.yml
. Insert the following below networks
:
volumes:
- ./custom-front/conf.override.json:/usr/share/nginx/html/conf.json
There should already be a commented block hinting that you can do this (just with a different path). You can delete this block, or, alternatively, place the file at the path given there and just remove the #
.
Create a folder custom-front
next to the docker-compose.yml
file
conf.override.json
. The contents of the file are below.custom-front/conf.override.json
This file will replace the conf.json
file. As the conf.json
is normally automatically generated at runtime from the configuration in your docker-compose.yml
, this is a bit trickier. Basically, the process boils down to this:
conf.json
"loginFormType": "ldap",
The question is: How do you get a valid conf.json
?
config.json
which you then have to adjust.You then have a valid, production-ready
docker cp taiga_taiga-front_1:/usr/share/nginx/html/conf.json conf.json
conf.json
you can just extend by the entry mentioned above. I’d recommend this method.Install the PIP package taiga-contrib-ldap-auth-ext
in your taiga-back
python virtualenv:
pip install taiga-contrib-ldap-auth-ext
If needed, change pip
to pip3
to use the Python 3 version.
For an even simpler installation, you can use our own Docker image: https://github.com/Monogramm/docker-taiga
taiga-back
Append the contents of the taiga-back
configuration section from this document to the file settings/common.py
(for Taiga >5.0) or settings/local.py
(for Taiga ≤5.0).
taiga-front
Change the loginFormType
setting to "ldap"
in dist/conf.json
:
"loginFormType": "ldap",
taiga-back
configurationIf you use the installation with Docker, put the following contents in the file custom-back/config.append.py
.
If you use the installation without Docker, append the following contents to the file settings/common.py
(for Taiga >5.0) or settings/local.py
(for Taiga ≤5.0).
python
INSTALLED_APPS += ["taiga_contrib_ldap_auth_ext"]
# Multiple LDAP servers are currently not supported, see
# https://github.com/Monogramm/taiga-contrib-ldap-auth-ext/issues/16
LDAP_SERVER = "ldaps://ldap.example.com"
LDAP_PORT = 636
LDAP_BIND_DN = "CN=SVC Account,OU=Service Accounts,OU=Servers,DC=example,DC=com"
LDAP_BIND_PASSWORD = "verysecurepassword"
LDAP_SEARCH_BASE = 'OU=DevTeam,DC=example,DC=net'
LDAP_USERNAME_ATTRIBUTE = "uid"
LDAP_EMAIL_ATTRIBUTE = "mail"
LDAP_FULL_NAME_ATTRIBUTE = "givenName"
LDAP_SAVE_LOGIN_PASSWORD = False
LDAP_MAP_USERNAME_TO_UID = None
LDAP_SERVER
and LDAP_PORT
: You will definitely have to change the server URL. If possible, try to keep the ldaps://
to use a secure connection. The port can likely stay as is, unless…ldaps://
to ldap://
and the port to 389.LDAP_START_TLS = True
, making the section look like this:python
LDAP_SERVER = "ldap://ldap.example.com"
LDAP_PORT = 389
LDAP_START_TLS = True
ldaps://
variant more.LDAP_BIND_DN
, LDAP_BIND_PASSWORD
: You will need to change them.LDAP_USERNAME_ATTRIBUTE
or LDAP_EMAIL_ATTRIBUTE
matching the user-provided login.LDAP_BIND_DN
is not specified or blank, an anonymous bind is attempted.LDAP_SEARCH_BASE
: The subtree where the users are located.LDAP_USERNAME_ATTRIBUTE
, LDAP_EMAIL_ATTRIBUTE
, LDAP_FULL_NAME_ATTRIBUTE
: These are the LDAP attributes used to get the username, email and full name shown in the Taiga application. They need to have a value in LDAP. Depending on your LDAP setup, you might need to change them.LDAP_SAVE_LOGIN_PASSWORD
: Set this to True
or remove the line if you want to store the passwords in the local database as well.LDAP_MAP_USERNAME_TO_UID
: This line fixes a bug. If omitted, the plugin will likely crash and no authentication is possible.normal
authentication if LDAP authentication fails. Add the following line to disable this and only allow LDAP login:python
LDAP_FALLBACK = ""
python
LDAP_SEARCH_FILTER_ADDITIONAL = '(mail=*)'
python
def _ldap_slugify(uid: str) -> str:
"""Map an LDAP username to a local DB user unique identifier.
Upon successful LDAP bind, will override returned username attribute
value. May result in unexpected failures if changed after the database
has been populated.
"""
# example: force lower-case
return uid.lower()
LDAP_MAP_USERNAME_TO_UID = _ldap_slugify
def _ldap_map_email(email: str) -> str:
...
def _ldap_map_name(name: str) -> str:
...
LDAP_MAP_EMAIL = _ldap_map_email
LDAP_MAP_NAME = _ldap_map_name
python
from ldap3 import Tls
import ssl
# Add or remove options or change values as necessary.
LDAP_TLS_CERTS = Tls(validate=ssl.CERT_NONE, version=ssl.PROTOCOL_TLSv1, ciphers='RSA+3DES')
python
LDAP_SAVE_LOGIN_PASSWORD = False
python
# Group search filter where $1 is the project slug and $2 is the role slug
#LDAP_GROUP_SEARCH_FILTER = 'CN=$2,OU=$1,OU=Groups,DC=example,DC=net'
# Use an attribute in the user entry for membership
#LDAP_USER_MEMBER_ATTRIBUTE = 'memberof,primaryGroupID'
# Starting point within LDAP structure to search for login group
#LDAP_GROUP_SEARCH_BASE = 'OU=Groups,DC=example,DC=net'
# Group classes filter
#LDAP_GROUP_FILTER = '(|(objectclass=group)(objectclass=groupofnames)(objectclass=groupofuniquenames))'
# Group member attribute
#LDAP_GROUP_MEMBER_ATTRIBUTE = 'memberof,primaryGroupID'
# Taiga super users group id
#LDAP_GROUP_ADMIN = 'OU=TaigaAdmin,DC=example,DC=net'
VmLYBbvJaf2kAqcrt5HjHdG6
.USER_EMAIL_ALLOWED_DOMAINS
config option, all LDAP email addresses will still be filtered through this list. Ensure that if USER_EMAIL_ALLOWED_DOMAINS
!= None
, that your corporate LDAP email domain is also listed there. This is due to the fact that LDAP users are automatically “registered” behind the scenes on their first login.PUBLIC_REGISTER_ENABLED
config option to False
. This will prevent any external user to register while still automatically register LDAP users on their first login.common.py
file in taiga-back
, you can also insert the configuration into config.py
. In our tests, both ways worked.