LDAP authentication plugin for self-hosted Taiga.io project management instances
Project description
LDAP authentication for Taiga
This plugin adds LDAP authentication support to self-hosted instances of the project management tool Taiga. It is a fork of Monogramm/taiga-contrib-ldap-auth-ext, which is a fork of ensky/taiga-contrib-ldap-auth.
🐋 Installation with Docker
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
- Edit the
taiga-backsection in thedocker-compose.yml: Replaceimage: taigaio/taiga-back:latestwithbuild: ./custom-back - Create a folder
custom-backnext to thedocker-compose.ymlfile - In this folder, create a file
config.append.py. Copy the contents of thetaiga-backconfiguration section from this document into it. - In this folder, also create a
Dockerfile. The contents are 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
FROM taigaio/taiga-back:latest
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-enhanced
Click here to expand explanation
The statements in the Dockerfile have the following effect:
FROM ...bases the image we build on the officialtaigaio/taiga-backimage.COPY ...andRUN ...copy theconfig.append.pyfile into the container, append it to/taiga-back/settings/config.pyand then delete it again.RUN pip install ...installs this plugin.
taiga-front
-
Edit the
taiga-frontsection in thedocker-compose.yml. Insert the following belownetworks: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-frontnext to thedocker-compose.ymlfile -
In this folder, create a 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:
- Somehow get a valid
conf.json - Create a modified version by adding the following entry somewhere in the JSON:
"loginFormType": "ldap",
The question is: How do you get a valid conf.json?
- The relevant section of the Taiga 30 min setup guide recommends to use an example
config.jsonwhich you then have to adjust. - Alternatively, you could also start the container first without any adjustments, and then copy the file out like this:
docker cp taiga_taiga-front_1:/usr/share/nginx/html/conf.json conf.json
You then have a valid, production-readyconf.jsonyou can just extend by the entry mentioned above. I'd recommend this method.
📦 Installation without Docker
Installation
Install the PIP package taiga-contrib-ldap-auth-enhanced in your taiga-back python virtualenv:
pip install taiga-contrib-ldap-auth-enhanced
If needed, change pip to pip3 to use the Python 3 version.
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",
🔧 Configuration
taiga-back configuration
If you use the installation with Docker, put something similar to the following in the file custom-back/config.append.py.
If you use the installation without Docker, append something similar to the following to the file settings/common.py (for Taiga >5.0) or settings/local.py (for Taiga ≤5.0):
INSTALLED_APPS += ["taiga_contrib_ldap_auth_enhanced"]
LDAP_SERVER = "ldaps://ldap.example.com"
LDAP_PORT = 636
# You can also use self-bind (without a dedicated bind account), expand
# the explanation below for details.
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
# You must include the following line (even though it seems trivial) in your
# config to fix a bug. If you omit this, stuff breaks.
LDAP_MAP_USERNAME_TO_UID = None
You need to change most of the values to match your setup.
Click here to expand configuration explanation
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...
- ... you run the LDAP server on a different (non-standard) port.
- ... you want to use unencrypted, insecure LDAP: In this case, change
ldaps://toldap://and the port to 389. - ... you want to use STARTTLS. In this case, you have to make the same changes as for unencrypted, insecure LDAP and set
LDAP_START_TLS = True, making the section look like this:LDAP_SERVER = "ldap://ldap.example.com" LDAP_PORT = 389 LDAP_START_TLS = True
What happens is that an unencrypted connection is established first, but then upgraded to a secure connection. This is less secure thanldaps://(see also the related discussion for STARTTLS for emails or this blog post), because an attacker could strip the “upgrade to secure connection” request causing the connection to remain insecure. It is still safer than an unecrypted connection, of course.
LDAP_BIND_DN, LDAP_BIND_PASSWORD: You will need to change them.
The bind user is a dedicated service account. The plugin will connect to the LDAP server using this service account and search for an LDAP entry that has a LDAP_USERNAME_ATTRIBUTE or LDAP_EMAIL_ATTRIBUTE matching the user-provided login.
If the search is successful, the found LDAP entry and the user-provided password are used to attempt a bind to LDAP. If the bind is successful, then we can say that the user is authorised to log in to Taiga.
If LDAP_BIND_DN is not specified or blank, an anonymous bind is attempted.
It is recommended to limit the service account and only allow it to read and search the LDAP structure (no write or other LDAP access). The credentials should also not be used for any other account on the network. This minimizes the damage in cases of a successful LDAP injection or if you ever accidentially give someone access to the configuration file (e.g. by committing it into version control or having misconfigured permissions). Use a suitably strong, ideally randomly generated password.
You can also use the credentials provided by the user to bind to LDAP (eliminating the need for a dedicated LDAP service account). To do so, do the following three things:
- Set
LDAP_BIND_WITH_USER_PROVIDED_CREDENTIALS = True - Insert the placeholder
<username>insideLDAP_BIND_DN, e.g. like this:"CN=<username>,OU=DevTeam,DC=example,DC=com". - Remove
LDAP_BIND_PASSWORD(it will not be used)
Taiga will then determine the LDAP bind user by replacing <username> with the user-provided username, and bind using the user-provided password.
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.
Additional configuration options
Click here to expand additional configuration options
By default, Taiga will fall back to normal authentication if LDAP authentication fails. Add the following line to disable this and only allow LDAP login:
LDAP_FALLBACK = ""
You can specify additional search criteria that will be ANDed using the following line:
LDAP_SEARCH_FILTER_ADDITIONAL = '(mail=*)'
If you want to change how the LDAP username, e-mail or name are mapped to the local database, you can use the following lines to do so:
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
To support alternative TLS ciphersuites, protocol versions or disable certificate validation (note that all of these options have the power to harm your security, so apply them with caution), use the following lines:
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')
To not store the passwords in the local database, use the following line:
LDAP_SAVE_LOGIN_PASSWORD = False
Group management via LDAP does not yet exist, see issues #15 and #17. However, the configuration would look a bit like this:
# 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'
Multiple LDAP servers are also not supported, see issue #16.
❓ Get Support
While I am trying my best to support you in setting up the plugin, I am afraid I sometimes take weeks to respond, so please do not get your hopes up.
💡 Further notes
- Security recommendation: The service account to perform the LDAP search should be configured to only allow reading/searching the LDAP structure. No other LDAP (or wider network) permissions should be granted for this user because you need to specify the service account password in the configuration file. A suitably strong password should be chosen, eg.
VmLYBbvJaf2kAqcrt5HjHdG6. - If you are using the Taiga's built-in
USER_EMAIL_ALLOWED_DOMAINSconfig option, all LDAP email addresses will still be filtered through this list. Ensure that ifUSER_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. - If you plan to only allow your LDAP users to access Taiga, set the
PUBLIC_REGISTER_ENABLEDconfig option toFalse. This will prevent any external user to register while still automatically register LDAP users on their first login. - Instead of appending to the
common.pyfile intaiga-back, you can also insert the configuration intoconfig.py. In our tests, both ways worked.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file taiga_contrib_ldap_auth_enhanced-0.6.tar.gz.
File metadata
- Download URL: taiga_contrib_ldap_auth_enhanced-0.6.tar.gz
- Upload date:
- Size: 39.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e32812906c09b9d3eaeb2f5078d5735718973854eb0219ec573df82f62b5c7f9
|
|
| MD5 |
804372fdf0a47f0b2b6d17ea01f4f049
|
|
| BLAKE2b-256 |
8b68a495261f8810e134a13c217f0f15f50014fb65fe9da290a516d7d4cb308d
|
Provenance
The following attestation bundles were made for taiga_contrib_ldap_auth_enhanced-0.6.tar.gz:
Publisher:
build-n-publish.yml on TuringTux/taiga-contrib-ldap-auth-enhanced
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
taiga_contrib_ldap_auth_enhanced-0.6.tar.gz -
Subject digest:
e32812906c09b9d3eaeb2f5078d5735718973854eb0219ec573df82f62b5c7f9 - Sigstore transparency entry: 639965568
- Sigstore integration time:
-
Permalink:
TuringTux/taiga-contrib-ldap-auth-enhanced@db2fd90e9fc0bdc2a5dd56cb3fef007908523b94 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/TuringTux
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-n-publish.yml@db2fd90e9fc0bdc2a5dd56cb3fef007908523b94 -
Trigger Event:
push
-
Statement type:
File details
Details for the file taiga_contrib_ldap_auth_enhanced-0.6-py3-none-any.whl.
File metadata
- Download URL: taiga_contrib_ldap_auth_enhanced-0.6-py3-none-any.whl
- Upload date:
- Size: 37.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4fe44d83b109dc06b58b703c4983c2fad26ad0531403b132f6b986c0ea33ca90
|
|
| MD5 |
6597dadb2f1e9c7a0223d428b9dbf7a3
|
|
| BLAKE2b-256 |
b6ed2abace3eac9424a414c4191944fab4602ecbba0ab3df827b396c4d656831
|
Provenance
The following attestation bundles were made for taiga_contrib_ldap_auth_enhanced-0.6-py3-none-any.whl:
Publisher:
build-n-publish.yml on TuringTux/taiga-contrib-ldap-auth-enhanced
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
taiga_contrib_ldap_auth_enhanced-0.6-py3-none-any.whl -
Subject digest:
4fe44d83b109dc06b58b703c4983c2fad26ad0531403b132f6b986c0ea33ca90 - Sigstore transparency entry: 639965572
- Sigstore integration time:
-
Permalink:
TuringTux/taiga-contrib-ldap-auth-enhanced@db2fd90e9fc0bdc2a5dd56cb3fef007908523b94 -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/TuringTux
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
build-n-publish.yml@db2fd90e9fc0bdc2a5dd56cb3fef007908523b94 -
Trigger Event:
push
-
Statement type: