Skip to content

Commit

Permalink
Add Active Directory support in LDAP Auth
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Mollberg committed Feb 4, 2015
1 parent a805941 commit 8f50f8f
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 5 deletions.
34 changes: 34 additions & 0 deletions nipap/nipap.conf.dist
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,40 @@ db_path = /etc/nipap/local_auth.db ; path to SQLite database used
#
#basedn = dc=test,dc=com ; base DN
#uri = ldaps://ldap.test.com ; LDAP server URI
#
# LDAP style
#binddn_fmt = uid={},dc=test,dc=com
#search = uid={} ; LDAP search filter
#
# Active Directory (UPN) style
#binddn_fmt = {}@test.com
#search = sAMAccountName={}
#
# {} in binddn_fmt is replaced by the username of the authenticating user.
#
## Group permissions
# Non-empty values for rw_group/ro_group requires the memberOf attribute to be
# present in LDAP.
#
# Examples:
#
# Everyone with an account can login and gets read/write access:
#rw_group =
#ro_group =
#
# Users in rw_group gets read/write access, everyone else gets read only access:
#rw_group = cn=tech,dc=test,dc=com ; Users in this group get rw access
#ro_group =
#
# Users in rw_group gets read/write access, users in ro_group get read
# only access. You need to be in either group to authenticate at all:
#rw_group = cn=tech,dc=test,dc=com ; Users in this group get rw access
#ro_group = cn=staff,dc=test,dc=com ; Users in this group get ro access
#
# Users get read/write access by default, users in ro_group gets read
# only access:
#rw_group =
#ro_group = cn=untrusted,dc=test,dc=com ; Users in this group get ro access

#
# Options for the WWW UI
Expand Down
46 changes: 41 additions & 5 deletions nipap/nipap/authlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ class LdapAuth(BaseAuth):

_ldap_uri = None
_ldap_basedn = None
_ldap_binddn_fmt = None
_ldap_search = None
_ldap_rw_group = None
_ldap_ro_group = None
_ldap_conn = None
_authenticated = None

Expand Down Expand Up @@ -294,6 +298,10 @@ def __init__(self, name, username, password, authoritative_source, auth_options=
BaseAuth.__init__(self, username, password, authoritative_source, name, auth_options)
self._ldap_uri = self._cfg.get('auth.backends.' + self.auth_backend, 'uri')
self._ldap_basedn = self._cfg.get('auth.backends.' + self.auth_backend, 'basedn')
self._ldap_binddn_fmt = self._cfg.get('auth.backends.' + self.auth_backend, 'binddn_fmt')
self._ldap_search = self._cfg.get('auth.backends.' + self.auth_backend, 'search')
self._ldap_ro_group = self._cfg.get('auth.backends.' + self.auth_backend, 'ro_group')
self._ldap_rw_group = self._cfg.get('auth.backends.' + self.auth_backend, 'rw_group')

self._logger.debug('Creating LdapAuth instance')

Expand All @@ -314,7 +322,7 @@ def authenticate(self):
return self._authenticated

try:
self._ldap_conn.simple_bind_s('uid=' + self.username + ',' + self._ldap_basedn, self.password)
self._ldap_conn.simple_bind_s(self._ldap_binddn_fmt.format(ldap.dn.escape_dn_chars(self.username)), self.password)
except ldap.SERVER_DOWN as exc:
raise AuthError('Could not connect to LDAP server')
except (ldap.INVALID_CREDENTIALS, ldap.INVALID_DN_SYNTAX,
Expand All @@ -327,17 +335,45 @@ def authenticate(self):

# auth succeeded
self.authenticated_as = self.username
self._authenticated = True
self.trusted = False
self.readonly = False

try:
res = self._ldap_conn.search_s(self._ldap_basedn, ldap.SCOPE_SUBTREE, 'uid=' + self.username, ['cn'])
res = self._ldap_conn.search_s(self._ldap_basedn, ldap.SCOPE_SUBTREE, self._ldap_search.format(ldap.dn.escape_dn_chars(self.username)), ['cn','memberOf'])
self.full_name = res[0][1]['cn'][0]
except:
# check for ro_group membership if ro_group is configured
if self._ldap_ro_group:
if self._ldap_ro_group in res[0][1]['memberOf']:
self.readonly = True
# check for rw_group membership if rw_group is configured
if self._ldap_rw_group:
if self._ldap_rw_group in res[0][1]['memberOf']:
self.readonly = False
else:
# if ro_group is configured, and the user is a member of
# neither the ro_group nor the rw_group, fail authentication.
if self._ldap_ro_group:
if self._ldap_ro_group not in res[0][1]['memberOf']:
self._authenticated = False
return self._authenticated
else:
self.readonly = True

except (ldap.NO_SUCH_OBJECT,ldap.OPERATIONS_ERROR,ldap.FILTER_ERROR,ldap.INVALID_DN_SYNTAX,ldap.SERVER_DOWN) as exc:
raise AuthError(exc)
except KeyError:
raise AuthError('LDAP attribute missing')
except IndexError:
self.full_name = ''
# authentication fails if either ro_group or rw_group are configured
# and the user is not found.
if self._ldap_rw_group or self._ldap_ro_group:
self._authenticated = False
return self._authenticated

self._logger.debug('successfully authenticated as %s, username %s' % (self.authenticated_as, self.username))
self._authenticated = True

self._logger.debug('successfully authenticated as %s, username %s, full_name %s, readonly %s' % (self.authenticated_as, self.username, self.full_name, str(self.readonly)))
return self._authenticated


Expand Down

0 comments on commit 8f50f8f

Please sign in to comment.