AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance.

1,594 views
Skip to first unread message

Mark Oldham

unread,
Apr 6, 2020, 7:23:20 AM4/6/20
to NetBox
Good Afternoon,

I'm fairly new to Netbox and I've only ever setup NetBox as a PoC and it was using local authentication.

We have chosen to now push ahead with the use of NetBox and I've got all the basic stuff configured without a problem but I've been stuck troubleshooting how to get LDAP Authentication working for a few days now and was hoping for a little bit of help.

When I try to login I'm getting the following error:

There was a problem with your request. Please contact an administrator.


The complete exception is provided below:

<class 'django.core.exceptions.ImproperlyConfigured'>
AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance.



I enabled logging for Django-ldap but that doesn't give much more help:


AUTH_LDAP_USER_SEARCH must be an LDAPSearch instance. while authenticating <username-remove>


I'm hoping somebody could help shed some light on my problems.

Thanks

Mark.

Kevin Beaudreau

unread,
Apr 6, 2020, 10:01:19 AM4/6/20
to Mark Oldham, NetBox
Hey Mark!

I feel your pain.  I'm new to this as well, but with help from this maillist, I am muddling through. 
This product would be much better if it included LDAP configuration in the app - but I understand the developers position (not complaining - just wishing).  

I used the docker image for LDAP that has django pre-installed.  i say that as some of the parameters might be different.

My AUTH_LDAP_USER_SEARCH looks like this (out of the box):
AUTH_LDAP_USER_SEARCH = LDAPSearch(AUTH_LDAP_USER_SEARCH_BASEDN,
                                   ldap.SCOPE_SUBTREE,
                                   "(" + AUTH_LDAP_USER_SEARCH_ATTR + "=%(user)s)")

But I really wanted to focus on using Groups rather than Users.  My GROUP Search is similar:
AUTH_LDAP_MIRROR_GROUPS = ["netbox-require-group", "netbox-admin-group", "netbox-superuser-group"]
AUTH_LDAP_GROUP_SEARCH_BASEDN = os.environ.get('AUTH_LDAP_GROUP_SEARCH_BASEDN', '')
AUTH_LDAP_GROUP_SEARCH_CLASS = os.environ.get('AUTH_LDAP_GROUP_SEARCH_CLASS', 'group')
AUTH_LDAP_GROUP_SEARCH = LDAPSearch(AUTH_LDAP_GROUP_SEARCH_BASEDN, ldap.SCOPE_SUBTREE,
                                    "(objectClass=" + AUTH_LDAP_GROUP_SEARCH_CLASS + ")")
AUTH_LDAP_GROUP_TYPE = import_group_type(os.environ.get('AUTH_LDAP_GROUP_TYPE', 'GroupOfNamesType'))

All of this is out-of-the-box configuration except the MIRROR_GROUPS.  I added that and the group names that I wanted to synchronize with django.

Now I just needed to provide the USER and GROUP BASEDN parameters.  That can go in the ldap_config file as well, but I put them in the docker-compose.override.yml file to keep the base files as clean as possible.

      AUTH_LDAP_USER_SEARCH_BASEDN: "OU=Users,DC=company,DC=com"
      AUTH_LDAP_GROUP_SEARCH_BASEDN: "OU=Users,DC=company,DC=com"


Hope this helps - I can send you more detailed files if needed.

--
You received this message because you are subscribed to the Google Groups "NetBox" group.
To unsubscribe from this group and stop receiving emails from it, send an email to netbox-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/netbox-discuss/70e0b14a-688a-4847-a84e-209eb82ea090%40googlegroups.com.

Moh Ahmed

unread,
Apr 6, 2020, 10:43:10 AM4/6/20
to NetBox
I have a sample config here: https://github.com/CENGN/netbox-kubernetes/blob/master/netbox-configmap.yaml#L80 

It is for configuring NetBox on a Kubernetes cluster but the line I quoted and anything below should be universal for the ldap_config.py file. 
To unsubscribe from this group and stop receiving emails from it, send an email to netbox-...@googlegroups.com.

Mark Oldham

unread,
Apr 8, 2020, 4:28:33 PM4/8/20
to NetBox
First of all I'd like to offer my thanks for your help.  The examples provided helped point me in the right direction however there was still more changes required and some certainly unexpected.

For example I wasn't so sure everything was installed as it should be even though I followed the instructions to the letter so I ran the upgrade.sh script and this resolved some of my issues but I was still unable to authenticate and I was sure that it was related to binding to the ldap.  I found another article online not specifically about Netbox saying you may need to provide the binding user in the format of user...@domain.local and sure enough this then changed the errors I was getting to be more related to the group memberships.

Anyhow I'm up and running with LDAP authentication now after a lot of little changes here and there, but thank you for your help.

Regards

Mark

Dirk Melvin

unread,
Apr 27, 2020, 10:56:15 AM4/27/20
to NetBox
Could you share the link to said article?

Mark Oldham

unread,
Apr 27, 2020, 12:31:51 PM4/27/20
to NetBox
I can't find the link but here is my sanitised config:

import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
#
#
# Server URI
AUTH_LDAP_SERVER_URI = "ldaps://ldapserver.domain.local"
# The following may be needed if you are binding to Active Directory.
AUTH_LDAP_CONNECTION_OPTIONS = {
    ldap.OPT_REFERRALS: 0
}
# Set the DN and password for the NetBox service account.
AUTH_LDAP_BIND_DN = "user...@domain.local"
AUTH_LDAP_BIND_PASSWORD = "passwordforuser"
# Include this setting if you want to ignore certificate errors. This might be needed to accept a self-signed cert.
# Note that this is a NetBox-specific setting which sets:
#     ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
LDAP_IGNORE_CERT_ERRORS = True
#
#
#
#
# Where to look for users
#                                    "(sAMAccountName=%(user)s)")
AUTH_LDAP_USER_SEARCH = LDAPSearch("OU=Users,OU=YOURCOMPANY,DC=domain,DC=local", ldap.SCOPE_SUBTREE,
                                    "(sAMAccountName=%(user)s)")
# This search ought to return all groups to which the user belongs. django_auth_ldap uses this to determine group
# hierarchy.
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("ou=Groups,ou=YOURCOMPANY,dc=domain,dc=local", ldap.SCOPE_SUBTREE,
                                    "(objectClass=group)")
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()

# Map user attributes to Django attributes
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail"
}
# Mirror LDAP group assignments.
AUTH_LDAP_MIRROR_GROUPS = True
# Define special user types using groups. Exercise great caution when assigning superuser status.
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
    "is_active": "CN=AllUsers,CN=Users,DC=domain,DC=local",
    "is_staff": "cn=StaffUsers,ou=Groups,ou=YOURCOMPANY,dc=domain,dc=local",
    "is_superuser": "cn=SuperUsers,ou=Groups,ou=YOURCOMPANY,dc=domain,dc=local"
}
# For more granular permissions, we can map LDAP groups to Django groups.
AUTH_LDAP_FIND_GROUP_PERMS = True
# Cache groups for one hour to reduce LDAP traffic
AUTH_LDAP_CACHE_TIMEOUT = 3600

Dirk Melvin

unread,
Apr 28, 2020, 1:51:29 PM4/28/20
to NetBox
Ok, using your example below, I am getting this error:

<class 'TypeError'>
initialize() argument 1 must be str, not tuple


Brian Candler

unread,
Apr 28, 2020, 3:15:49 PM4/28/20
to NetBox
When I see this error, it usually means I've put a spurious comma after a value.

>>> foo
1
>>> foo = 1
>>> foo
1
>>> bar = 1,
>>> bar
(1,)
>>> type(bar)
<class 'tuple'>
Reply all
Reply to author
Forward
0 new messages