From 040fadb0c300b9675bcec17832da4cdb4ed40f40 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 3 Jun 2020 15:42:24 -0400 Subject: [PATCH 1/2] Move LDAP authentication support to LDAPBackend --- netbox/netbox/authentication.py | 48 +++++++++++++++++++++++ netbox/netbox/settings.py | 69 --------------------------------- 2 files changed, 48 insertions(+), 69 deletions(-) diff --git a/netbox/netbox/authentication.py b/netbox/netbox/authentication.py index 02b0be0f3..10d2d1b09 100644 --- a/netbox/netbox/authentication.py +++ b/netbox/netbox/authentication.py @@ -3,6 +3,7 @@ import logging from django.conf import settings from django.contrib.auth.backends import ModelBackend, RemoteUserBackend as _RemoteUserBackend from django.contrib.auth.models import Group +from django.core.exceptions import ImproperlyConfigured from django.db.models import Q from users.models import ObjectPermission @@ -132,3 +133,50 @@ class RemoteUserBackend(_RemoteUserBackend): def has_perm(self, user_obj, perm, obj=None): return False + + +class LDAPBackend: + + def __new__(cls, *args, **kwargs): + try: + import ldap + from django_auth_ldap.backend import LDAPBackend as LDAPBackend_, LDAPSettings + except ImportError: + raise ImproperlyConfigured( + "LDAP authentication has been configured, but django-auth-ldap is not installed." + ) + + try: + from netbox import ldap_config + except ImportError: + raise ImproperlyConfigured( + "ldap_config.py does not exist" + ) + + try: + getattr(ldap_config, 'AUTH_LDAP_SERVER_URI') + except AttributeError: + raise ImproperlyConfigured( + "Required parameter AUTH_LDAP_SERVER_URI is missing from ldap_config.py." + ) + + # Create a new instance of django-auth-ldap's LDAPBackend + obj = LDAPBackend_() + + # Read LDAP configuration parameters from ldap_config.py instead of settings.py + settings = LDAPSettings() + for param in dir(ldap_config): + if param.startswith(settings._prefix): + setattr(settings, param[10:], getattr(ldap_config, param)) + obj.settings = settings + + # Optionally disable strict certificate checking + if getattr(ldap_config, 'LDAP_IGNORE_CERT_ERRORS', False): + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) + + # Enable logging for django_auth_ldap + ldap_logger = logging.getLogger('django_auth_ldap') + ldap_logger.addHandler(logging.StreamHandler()) + ldap_logger.setLevel(logging.DEBUG) + + return obj diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index eb9fab57a..bc1a8c2e7 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -378,75 +378,6 @@ LOGIN_URL = '/{}login/'.format(BASE_PATH) CSRF_TRUSTED_ORIGINS = ALLOWED_HOSTS - -# -# LDAP authentication (optional) -# - -try: - from netbox import ldap_config as LDAP_CONFIG -except ImportError: - LDAP_CONFIG = None - -if LDAP_CONFIG is not None: - - # Check that django_auth_ldap is installed - try: - import ldap - import django_auth_ldap - except ImportError: - raise ImproperlyConfigured( - "LDAP authentication has been configured, but django-auth-ldap is not installed. Remove " - "netbox/ldap_config.py to disable LDAP." - ) - - # Required configuration parameters - try: - AUTH_LDAP_SERVER_URI = getattr(LDAP_CONFIG, 'AUTH_LDAP_SERVER_URI') - except AttributeError: - raise ImproperlyConfigured( - "Required parameter AUTH_LDAP_SERVER_URI is missing from ldap_config.py." - ) - - # Optional configuration parameters - AUTH_LDAP_ALWAYS_UPDATE_USER = getattr(LDAP_CONFIG, 'AUTH_LDAP_ALWAYS_UPDATE_USER', True) - AUTH_LDAP_AUTHORIZE_ALL_USERS = getattr(LDAP_CONFIG, 'AUTH_LDAP_AUTHORIZE_ALL_USERS', False) - AUTH_LDAP_BIND_AS_AUTHENTICATING_USER = getattr(LDAP_CONFIG, 'AUTH_LDAP_BIND_AS_AUTHENTICATING_USER', False) - AUTH_LDAP_BIND_DN = getattr(LDAP_CONFIG, 'AUTH_LDAP_BIND_DN', '') - AUTH_LDAP_BIND_PASSWORD = getattr(LDAP_CONFIG, 'AUTH_LDAP_BIND_PASSWORD', '') - AUTH_LDAP_CACHE_TIMEOUT = getattr(LDAP_CONFIG, 'AUTH_LDAP_CACHE_TIMEOUT', 0) - AUTH_LDAP_CONNECTION_OPTIONS = getattr(LDAP_CONFIG, 'AUTH_LDAP_CONNECTION_OPTIONS', {}) - AUTH_LDAP_DENY_GROUP = getattr(LDAP_CONFIG, 'AUTH_LDAP_DENY_GROUP', None) - AUTH_LDAP_FIND_GROUP_PERMS = getattr(LDAP_CONFIG, 'AUTH_LDAP_FIND_GROUP_PERMS', False) - AUTH_LDAP_GLOBAL_OPTIONS = getattr(LDAP_CONFIG, 'AUTH_LDAP_GLOBAL_OPTIONS', {}) - AUTH_LDAP_GROUP_SEARCH = getattr(LDAP_CONFIG, 'AUTH_LDAP_GROUP_SEARCH', None) - AUTH_LDAP_GROUP_TYPE = getattr(LDAP_CONFIG, 'AUTH_LDAP_GROUP_TYPE', None) - AUTH_LDAP_MIRROR_GROUPS = getattr(LDAP_CONFIG, 'AUTH_LDAP_MIRROR_GROUPS', None) - AUTH_LDAP_MIRROR_GROUPS_EXCEPT = getattr(LDAP_CONFIG, 'AUTH_LDAP_MIRROR_GROUPS_EXCEPT', None) - AUTH_LDAP_PERMIT_EMPTY_PASSWORD = getattr(LDAP_CONFIG, 'AUTH_LDAP_PERMIT_EMPTY_PASSWORD', False) - AUTH_LDAP_REQUIRE_GROUP = getattr(LDAP_CONFIG, 'AUTH_LDAP_REQUIRE_GROUP', None) - AUTH_LDAP_NO_NEW_USERS = getattr(LDAP_CONFIG, 'AUTH_LDAP_NO_NEW_USERS', False) - AUTH_LDAP_START_TLS = getattr(LDAP_CONFIG, 'AUTH_LDAP_START_TLS', False) - AUTH_LDAP_USER_QUERY_FIELD = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_QUERY_FIELD', None) - AUTH_LDAP_USER_ATTRLIST = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_ATTRLIST', None) - AUTH_LDAP_USER_ATTR_MAP = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_ATTR_MAP', {}) - AUTH_LDAP_USER_DN_TEMPLATE = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_DN_TEMPLATE', None) - AUTH_LDAP_USER_FLAGS_BY_GROUP = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_FLAGS_BY_GROUP', {}) - AUTH_LDAP_USER_SEARCH = getattr(LDAP_CONFIG, 'AUTH_LDAP_USER_SEARCH', None) - - # Optionally disable strict certificate checking - if getattr(LDAP_CONFIG, 'LDAP_IGNORE_CERT_ERRORS', False): - ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) - - # Prepend LDAPBackend to the authentication backends list - AUTHENTICATION_BACKENDS.insert(0, 'django_auth_ldap.backend.LDAPBackend') - - # Enable logging for django_auth_ldap - ldap_logger = logging.getLogger('django_auth_ldap') - ldap_logger.addHandler(logging.StreamHandler()) - ldap_logger.setLevel(logging.DEBUG) - - # # Caching # From dc161d9f2f260e8bae77b3925ee9b023e7acd25b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 3 Jun 2020 15:57:11 -0400 Subject: [PATCH 2/2] Update LDAP configuration documentation --- docs/configuration/optional-settings.md | 5 ++++- docs/installation/5-ldap.md | 11 +++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 31ee39a5f..9fddbe82a 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -386,7 +386,10 @@ NetBox can be configured to support remote user authentication by inferring user Default: `'netbox.authentication.RemoteUserBackend'` -Python path to the custom [Django authentication backend](https://docs.djangoproject.com/en/stable/topics/auth/customizing/) to use for external user authentication, if not using NetBox's built-in backend. (Requires `REMOTE_AUTH_ENABLED`.) +Python path to the custom [Django authentication backend](https://docs.djangoproject.com/en/stable/topics/auth/customizing/) to use for external user authentication. NetBox provides two built-in backends (listed below), though backends may also be provided via other packages. + +* `netbox.authentication.RemoteUserBackend` +* `netbox.authentication.LDAPBackend` --- diff --git a/docs/installation/5-ldap.md b/docs/installation/5-ldap.md index 2fd88b841..bb1300c08 100644 --- a/docs/installation/5-ldap.md +++ b/docs/installation/5-ldap.md @@ -36,7 +36,13 @@ Once installed, add the package to `local_requirements.txt` to ensure it is re-i ## Configuration -Create a file in the same directory as `configuration.py` (typically `netbox/netbox/`) named `ldap_config.py`. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](http://django-auth-ldap.readthedocs.io/). +First, enable the LDAP authentication backend in `configuration.py`. (Be sure to overwrite this definition if it is already set to `RemoteUserBackend`.) + +```python +REMOTE_AUTH_BACKEND = 'netbox.authentication.LDAPBackend' +``` + +Next, create a file in the same directory as `configuration.py` (typically `netbox/netbox/`) named `ldap_config.py`. Define all of the parameters required below in `ldap_config.py`. Complete documentation of all `django-auth-ldap` configuration options is included in the project's [official documentation](http://django-auth-ldap.readthedocs.io/). ### General Server Configuration @@ -145,7 +151,8 @@ logfile = "/opt/netbox/logs/django-ldap-debug.log" my_logger = logging.getLogger('django_auth_ldap') my_logger.setLevel(logging.DEBUG) handler = logging.handlers.RotatingFileHandler( - logfile, maxBytes=1024 * 500, backupCount=5) + logfile, maxBytes=1024 * 500, backupCount=5 +) my_logger.addHandler(handler) ```