mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Native LDAP support (#5226)
* Added basic ldap support * Added new settings to config template * Added missing apk dependency to dockerfile * update requirements.txt * Remove requirements and added docs * Update advanced.md * Added more ldap options * allow direct bind * add ldap debug mode * add ldap global_options * add start_tls * use get_boolean_setting * Update advanced.md to use a warning box * fix: style * Update advanced.md * Remove ldap install instructions for non docker installs
This commit is contained in:
parent
a6dbe185c6
commit
8ec04028d5
@ -28,7 +28,9 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive && \
|
||||
# PostgreSQL support
|
||||
libpq-dev \
|
||||
# MySQL / MariaDB support
|
||||
default-libmysqlclient-dev mariadb-client && \
|
||||
default-libmysqlclient-dev mariadb-client \
|
||||
# LDAP support
|
||||
libldap2-dev libsasl2-dev && \
|
||||
apt-get autoclean && apt-get autoremove
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
|
@ -58,7 +58,7 @@ RUN apk add --no-cache \
|
||||
# Image format support
|
||||
libjpeg libwebp zlib \
|
||||
# Weasyprint requirements : https://doc.courtbouillon.org/weasyprint/stable/first_steps.html#alpine-3-12
|
||||
py3-pip py3-pillow py3-cffi py3-brotli pango poppler-utils \
|
||||
py3-pip py3-pillow py3-cffi py3-brotli pango poppler-utils openldap \
|
||||
# SQLite support
|
||||
sqlite \
|
||||
# PostgreSQL support
|
||||
@ -84,7 +84,7 @@ RUN if [ `apk --print-arch` = "armv7" ]; then \
|
||||
fi
|
||||
|
||||
RUN apk add --no-cache --virtual .build-deps \
|
||||
gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev \
|
||||
gcc g++ musl-dev openssl-dev libffi-dev cargo python3-dev openldap-dev \
|
||||
# Image format dev libs
|
||||
jpeg-dev openjpeg-dev libwebp-dev zlib-dev \
|
||||
# DB specific dev libs
|
||||
|
@ -291,6 +291,63 @@ AUTHENTICATION_BACKENDS = CONFIG.get('authentication_backends', [
|
||||
"sesame.backends.ModelBackend", # Magic link login django-sesame
|
||||
])
|
||||
|
||||
# LDAP support
|
||||
LDAP_AUTH = get_boolean_setting("INVENTREE_LDAP_ENABLED", "ldap.enabled", False)
|
||||
if LDAP_AUTH:
|
||||
import ldap
|
||||
from django_auth_ldap.config import LDAPSearch
|
||||
|
||||
AUTHENTICATION_BACKENDS.append("django_auth_ldap.backend.LDAPBackend")
|
||||
|
||||
# debug mode to troubleshoot configuration
|
||||
LDAP_DEBUG = get_boolean_setting("INVENTREE_LDAP_DEBUG", "ldap.debug", False)
|
||||
if LDAP_DEBUG:
|
||||
if "loggers" not in LOGGING:
|
||||
LOGGING["loggers"] = {}
|
||||
LOGGING["loggers"]["django_auth_ldap"] = {"level": "DEBUG", "handlers": ["console"]}
|
||||
|
||||
# get global options from dict and use ldap.OPT_* as keys and values
|
||||
global_options_dict = get_setting("INVENTREE_LDAP_GLOBAL_OPTIONS", "ldap.global_options", {}, dict)
|
||||
global_options = {}
|
||||
for k, v in global_options_dict.items():
|
||||
# keys are always ldap.OPT_* constants
|
||||
k_attr = getattr(ldap, k, None)
|
||||
if not k.startswith("OPT_") or k_attr is None:
|
||||
print(f"[LDAP] ldap.global_options, key '{k}' not found, skipping...")
|
||||
continue
|
||||
|
||||
# values can also be other strings, e.g. paths
|
||||
v_attr = v
|
||||
if v.startswith("OPT_"):
|
||||
v_attr = getattr(ldap, v, None)
|
||||
|
||||
if v_attr is None:
|
||||
print(f"[LDAP] ldap.global_options, value key '{v}' not found, skipping...")
|
||||
continue
|
||||
|
||||
global_options[k_attr] = v_attr
|
||||
AUTH_LDAP_GLOBAL_OPTIONS = global_options
|
||||
if LDAP_DEBUG:
|
||||
print("[LDAP] ldap.global_options =", global_options)
|
||||
|
||||
AUTH_LDAP_SERVER_URI = get_setting("INVENTREE_LDAP_SERVER_URI", "ldap.server_uri")
|
||||
AUTH_LDAP_START_TLS = get_boolean_setting("INVENTREE_LDAP_START_TLS", "ldap.start_tls", False)
|
||||
AUTH_LDAP_BIND_DN = get_setting("INVENTREE_LDAP_BIND_DN", "ldap.bind_dn")
|
||||
AUTH_LDAP_BIND_PASSWORD = get_setting("INVENTREE_LDAP_BIND_PASSWORD", "ldap.bind_password")
|
||||
AUTH_LDAP_USER_SEARCH = LDAPSearch(
|
||||
get_setting("INVENTREE_LDAP_SEARCH_BASE_DN", "ldap.search_base_dn"),
|
||||
ldap.SCOPE_SUBTREE,
|
||||
str(get_setting("INVENTREE_LDAP_SEARCH_FILTER_STR", "ldap.search_filter_str", "(uid= %(user)s)"))
|
||||
)
|
||||
AUTH_LDAP_USER_DN_TEMPLATE = get_setting("INVENTREE_LDAP_USER_DN_TEMPLATE", "ldap.user_dn_template")
|
||||
AUTH_LDAP_USER_ATTR_MAP = get_setting("INVENTREE_LDAP_USER_ATTR_MAP", "ldap.user_attr_map", {
|
||||
'first_name': 'givenName',
|
||||
'last_name': 'sn',
|
||||
'email': 'mail',
|
||||
}, dict)
|
||||
AUTH_LDAP_ALWAYS_UPDATE_USER = get_boolean_setting("INVENTREE_LDAP_ALWAYS_UPDATE_USER", "ldap.always_update_user", True)
|
||||
AUTH_LDAP_CACHE_TIMEOUT = get_setting("INVENTREE_LDAP_CACHE_TIMEOUT", "ldap.cache_timeout", 3600, int)
|
||||
|
||||
DEBUG_TOOLBAR_ENABLED = DEBUG and get_setting('INVENTREE_DEBUG_TOOLBAR', 'debug_toolbar', False)
|
||||
|
||||
# If the debug toolbar is enabled, add the modules
|
||||
|
@ -233,6 +233,43 @@ remote_login_header: HTTP_REMOTE_USER
|
||||
# KEYCLOAK_URL: 'https://keycloak.custom/auth'
|
||||
# KEYCLOAK_REALM: 'master'
|
||||
|
||||
# Add LDAP support
|
||||
# ldap:
|
||||
# enabled: false
|
||||
# debug: false # enable debug mode to troubleshoot ldap configuration
|
||||
# server_uri: ldaps://example.org
|
||||
# bind_dn: cn=admin,dc=example,dc=org
|
||||
# bind_password: admin_password
|
||||
# search_base_dn: cn=Users,dc=example,dc=org
|
||||
|
||||
# # enable TLS encryption over the standard LDAP port,
|
||||
# # see: https://django-auth-ldap.readthedocs.io/en/latest/reference.html#auth-ldap-start-tls
|
||||
# # start_tls: false
|
||||
|
||||
# # uncomment if you want to use direct bind, bind_dn and bin_password is not necessary then
|
||||
# # user_dn_template: "uid=%(user)s,dc=example,dc=org"
|
||||
|
||||
# # uncomment to set advanced global options, see https://www.python-ldap.org/en/latest/reference/ldap.html#ldap-options
|
||||
# # for all available options (keys and values starting with OPT_ get automatically converted to python-ldap keys)
|
||||
# # global_options:
|
||||
# # OPT_X_TLS_REQUIRE_CERT: OPT_X_TLS_NEVER
|
||||
# # OPT_X_TLS_CACERTFILE: /opt/inventree/ldapca.pem
|
||||
|
||||
# # uncomment for advanced filter search, default: uid=%(user)s
|
||||
# # search_filter_str:
|
||||
|
||||
# # uncomment for advanced user attribute mapping (in the format <InvenTree attribute>: <LDAP attribute>)
|
||||
# # user_attr_map:
|
||||
# # first_name: givenName
|
||||
# # last_name: sn
|
||||
# # email: mail
|
||||
|
||||
# # always update the user on each login, default: true
|
||||
# # always_update_user: true
|
||||
|
||||
# # cache timeout to reduce traffic with LDAP server, default: 3600 (1h)
|
||||
# # cache_timeout: 3600
|
||||
|
||||
# Customization options
|
||||
# Add custom messages to the login page or main interface navbar or exchange the logo
|
||||
# Use environment variable INVENTREE_CUSTOMIZE or INVENTREE_CUSTOM_LOGO
|
||||
|
@ -14,3 +14,7 @@ mariadb>=1.0.7,<1.1.0
|
||||
|
||||
# gunicorn web server
|
||||
gunicorn>=20.1.0
|
||||
|
||||
# LDAP required packages
|
||||
django-auth-ldap # Django integration for ldap auth
|
||||
python-ldap # LDAP auth support
|
||||
|
@ -40,3 +40,30 @@ The installer code is used to identify the way InvenTree was installed. If you v
|
||||
| DIO | Installed using digital ocean marketplace[^1] | No |
|
||||
|
||||
[^1]: Starting with fresh installs of 0.12.0 this code is set. Versions installed before 0.12.0 do not have this code set even after upgrading to 0.12.0.
|
||||
|
||||
## Authentication
|
||||
|
||||
### LDAP
|
||||
|
||||
You can link your InvenTree server to an LDAP server.
|
||||
|
||||
!!! warning "Important"
|
||||
This feature is currently only available for docker installs.
|
||||
|
||||
Next you can start configuring the connection. Either use the config file or set the environment variables.
|
||||
|
||||
| config key | ENV Variable | Description |
|
||||
| --- | --- | --- |
|
||||
| `ldap.enabled` | `INVENTREE_LDAP_ENABLED` | Set this to `True` to enable LDAP. |
|
||||
| `ldap.debug` | `INVENTREE_LDAP_DEBUG` | Set this to `True` to activate debug mode, useful for troubleshooting ldap configurations. |
|
||||
| `ldap.server_uri` | `INVENTREE_LDAP_SERVER_URI` | LDAP Server URI, e.g. `ldaps://example.org` |
|
||||
| `ldap.start_tls` | `INVENTREE_LDAP_START_TLS` | Enable TLS encryption over the standard LDAP port, [see](https://django-auth-ldap.readthedocs.io/en/latest/reference.html#auth-ldap-start-tls). (You can set TLS options via `ldap.global_options`) |
|
||||
| `ldap.bind_dn` | `INVENTREE_LDAP_BIND_DN` | LDAP bind dn, e.g. `cn=admin,dc=example,dc=org` |
|
||||
| `ldap.bind_password` | `INVENTREE_LDAP_BIND_PASSWORD` | LDAP bind password |
|
||||
| `ldap.search_base_dn` | `INVENTREE_LDAP_SEARCH_BASE_DN` | LDAP search base dn, e.g. `cn=Users,dc=example,dc=org` |
|
||||
| `ldap.user_dn_template` | `INVENTREE_LDAP_USER_DN_TEMPLATE` | use direct bind as auth user, `ldap.bind_dn` and `ldap.bin_password` is not necessary then, e.g. `uid=%(user)s,dc=example,dc=org` |
|
||||
| `ldap.global_options` | `INVENTREE_LDAP_GLOBAL_OPTIONS` | set advanced options as dict, e.g. TLS settings. For a list of all available options, see [python-ldap docs](https://www.python-ldap.org/en/latest/reference/ldap.html#ldap-options). (keys and values starting with OPT_ get automatically converted to `python-ldap` keys) |
|
||||
| `ldap.search_filter_str`| `INVENTREE_LDAP_SEARCH_FILTER_STR` | LDAP search filter str, default: `uid=%(user)s` |
|
||||
| `ldap.user_attr_map` | `INVENTREE_LDAP_USER_ATTR_MAP` | LDAP <-> Inventree user attribute map, can be json if used as env, in yml directly specify the object. default: `{"first_name": "givenName", "last_name": "sn", "email": "mail"}` |
|
||||
| `ldap.always_update_user` | `INVENTREE_LDAP_ALWAYS_UPDATE_USER` | Always update the user on each login, default: `true` |
|
||||
| `ldap.cache_timeout` | `INVENTREE_LDAP_CACHE_TIMEOUT` | cache timeout to reduce traffic with LDAP server, default: `3600` (1h) |
|
||||
|
Loading…
Reference in New Issue
Block a user