ldap_auth.py pep8, thanks Kory

This commit is contained in:
mdipierro
2012-07-12 11:26:45 -05:00
parent d66d46be7e
commit d9802c374a
2 changed files with 214 additions and 207 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.00.0 (2012-07-11 23:13:56) dev Version 2.00.0 (2012-07-12 11:26:41) dev
+213 -206
View File
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# last tinkered with by korylprince at gmail.com on 2012-07-11 # last tinkered with by korylprince at gmail.com on 2012-07-12
# #
import sys import sys
import logging import logging
@@ -13,24 +13,25 @@ except Exception, e:
logging.error('missing ldap, try "easy_install python-ldap"') logging.error('missing ldap, try "easy_install python-ldap"')
raise e raise e
def ldap_auth(server = 'ldap', port = None,
base_dn = 'ou=users,dc=domain,dc=com', def ldap_auth(server='ldap', port=None,
mode = 'uid', secure = False, cert_path = None, cert_file = None, base_dn='ou=users,dc=domain,dc=com',
bind_dn = None, bind_pw = None, filterstr = 'objectClass=*', mode='uid', secure=False, cert_path=None, cert_file=None,
username_attrib = 'uid', bind_dn=None, bind_pw=None, filterstr='objectClass=*',
custom_scope = 'subtree', username_attrib='uid',
allowed_groups = None, custom_scope='subtree',
manage_user = False, allowed_groups=None,
user_firstname_attrib = 'cn:1', manage_user=False,
user_lastname_attrib = 'cn:2', user_firstname_attrib='cn:1',
user_mail_attrib = 'mail', user_lastname_attrib='cn:2',
manage_groups = False, user_mail_attrib='mail',
db = None, manage_groups=False,
group_dn = None, db=None,
group_name_attrib = 'cn', group_dn=None,
group_member_attrib = 'memberUid', group_name_attrib='cn',
group_filterstr = 'objectClass=*', group_member_attrib='memberUid',
logging_level = 'error'): group_filterstr='objectClass=*',
logging_level='error'):
""" """
to use ldap login with MS Active Directory: to use ldap login with MS Active Directory:
@@ -50,7 +51,8 @@ def ldap_auth(server = 'ldap', port = None,
auth.settings.login_methods.append(ldap_auth( auth.settings.login_methods.append(ldap_auth(
server='my.ldap.server', base_dn='ou=Users,dc=domain,dc=com')) server='my.ldap.server', base_dn='ou=Users,dc=domain,dc=com'))
to use ldap login with OpenLDAP and subtree search and (optionally) multiple DNs: to use ldap login with OpenLDAP and subtree search and (optionally)
multiple DNs:
auth.settings.login_methods.append(ldap_auth( auth.settings.login_methods.append(ldap_auth(
mode='uid_r', server='my.ldap.server', mode='uid_r', server='my.ldap.server',
@@ -63,81 +65,87 @@ def ldap_auth(server = 'ldap', port = None,
base_dn='ou=Users,dc=domain,dc=com')) base_dn='ou=Users,dc=domain,dc=com'))
or you can full customize the search for user: or you can full customize the search for user:
auth.settings.login_methods.append(ldap_auth( auth.settings.login_methods.append(ldap_auth(
mode='custom', server='my.ldap.server', mode='custom', server='my.ldap.server',
base_dn='ou=Users,dc=domain,dc=com', base_dn='ou=Users,dc=domain,dc=com',
username_attrib='uid', username_attrib='uid',
custom_scope='subtree')) custom_scope='subtree'))
the custom_scope can be: base, onelevel, subtree.
If using secure ldaps:// pass secure=True and cert_path="..."
If ldap is using GnuTLS then you need cert_file="..." instead cert_path because
cert_path isn't implemented in GnuTLS :(
If you need to bind to the directory with an admin account in order to search it then specify bind_dn & bind_pw to use for this. the custom_scope can be: base, onelevel, subtree.
If using secure ldaps:// pass secure=True and cert_path="..."
If ldap is using GnuTLS then you need cert_file="..." instead cert_path
because cert_path isn't implemented in GnuTLS :(
If you need to bind to the directory with an admin account in order to
search it then specify bind_dn & bind_pw to use for this.
- currently only implemented for Active Directory - currently only implemented for Active Directory
If you need to restrict the set of allowed users (e.g. to members of a department) then specify If you need to restrict the set of allowed users (e.g. to members of a
a rfc4515 search filter string. department) then specify an rfc4515 search filter string.
- currently only implemented for mode in ['ad', 'company', 'uid_r'] - currently only implemented for mode in ['ad', 'company', 'uid_r']
You can manage user attribute first name, last name, email from ldap:
You can manage user attributes first name, last name, email from ldap:
auth.settings.login_methods.append(ldap_auth(...as usual..., auth.settings.login_methods.append(ldap_auth(...as usual...,
manage_user = True, manage_user=True,
user_firstname_attrib = 'cn:1', user_firstname_attrib='cn:1',
user_lastname_attrib = 'cn:2', user_lastname_attrib='cn:2',
user_mail_attrib = 'mail' user_mail_attrib='mail'
)) ))
Where: Where:
manage_user - let web2py handle user data from ldap manage_user - let web2py handle user data from ldap
user_firstname_attrib - the attribute containing the user's first name user_firstname_attrib - the attribute containing the user's first name
optionally you can specify parts. optionally you can specify parts.
Example: cn: "John Smith" - 'cn:1' = 'John' Example: cn: "John Smith" - 'cn:1'='John'
user_lastname_attrib - the attribute containing the user's last name user_lastname_attrib - the attribute containing the user's last name
optionally you can specify parts. optionally you can specify parts.
Example: cn: "John Smith" - 'cn:2' = 'Smith' Example: cn: "John Smith" - 'cn:2'='Smith'
user_mail_attrib - the attribure containing the user's email address user_mail_attrib - the attribute containing the user's email address
If you need group control from ldap to web2py app's database feel free to set: If you need group control from ldap to web2py app's database feel free
to set:
auth.settings.login_methods.append(ldap_auth(...as usual..., auth.settings.login_methods.append(ldap_auth(...as usual...,
manage_groups = True, manage_groups=True,
db = db, db=db,
group_dn = 'ou=Groups,dc=domain,dc=com', group_dn='ou=Groups,dc=domain,dc=com',
group_name_attrib = 'cn', group_name_attrib='cn',
group_member_attrib = 'memberUid', group_member_attrib='memberUid',
group_filterstr = 'objectClass=*' group_filterstr='objectClass=*'
)) ))
Where: Where:
manage_group - let web2py handle the groups from ldap manage_group - let web2py handle the groups from ldap
db - is the database object (need to have auth_user, auth_group, auth_membership) db - is the database object (need to have auth_user, auth_group,
auth_membership)
group_dn - the ldap branch of the groups group_dn - the ldap branch of the groups
group_name_attrib - the attribute where the group name is stored group_name_attrib - the attribute where the group name is stored
group_member_attrib - the attribute containing the group members name group_member_attrib - the attribute containing the group members name
group_filterstr - as the filterstr but for group select group_filterstr - as the filterstr but for group select
You can restrict login access to specific groups if you specify: You can restrict login access to specific groups if you specify:
auth.settings.login_methods.append(ldap_auth(...as usual..., auth.settings.login_methods.append(ldap_auth(...as usual...,
allowed_groups = [...], allowed_groups=[...],
group_dn = 'ou=Groups,dc=domain,dc=com', group_dn='ou=Groups,dc=domain,dc=com',
group_name_attrib = 'cn', group_name_attrib='cn',
group_member_attrib = 'memberUid', # use 'member' for Active Directory group_member_attrib='memberUid',#use 'member' for Active Directory
group_filterstr = 'objectClass=*' group_filterstr='objectClass=*'
)) ))
Where: Where:
allowed_groups - a list with allowed ldap group names allowed_groups - a list with allowed ldap group names
group_dn - the ldap branch of the groups group_dn - the ldap branch of the groups
group_name_attrib - the attribute where the group name is stored group_name_attrib - the attribute where the group name is stored
group_member_attrib - the attibute containing the group members name group_member_attrib - the attribute containing the group members name
group_filterstr - as the filterstr but for group select group_filterstr - as the filterstr but for group select
If using Active Directory you must specify bind_dn and bind_pw for allowed_groups unless anonymous bind works. If using Active Directory you must specify bind_dn and bind_pw for
allowed_groups unless anonymous bind works.
You can set the logging level with the "logging_level" parameter, default You can set the logging level with the "logging_level" parameter, default
is "error" and can be set to error, warning, info, debug. is "error" and can be set to error, warning, info, debug.
""" """
@@ -150,32 +158,34 @@ def ldap_auth(server = 'ldap', port = None,
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
elif logging_level == 'debug': elif logging_level == 'debug':
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
def ldap_auth_aux(username, def ldap_auth_aux(username,
password, password,
ldap_server = server, ldap_server=server,
ldap_port = port, ldap_port=port,
ldap_basedn = base_dn, ldap_basedn=base_dn,
ldap_mode = mode, ldap_mode=mode,
ldap_binddn = bind_dn, ldap_binddn=bind_dn,
ldap_bindpw = bind_pw, ldap_bindpw=bind_pw,
secure = secure, secure=secure,
cert_path = cert_path, cert_path=cert_path,
cert_file = cert_file, cert_file=cert_file,
filterstr = filterstr, filterstr=filterstr,
username_attrib = username_attrib, username_attrib=username_attrib,
custom_scope = custom_scope, custom_scope=custom_scope,
manage_user = manage_user, manage_user=manage_user,
user_firstname_attrib = user_firstname_attrib, user_firstname_attrib=user_firstname_attrib,
user_lastname_attrib = user_lastname_attrib, user_lastname_attrib=user_lastname_attrib,
user_mail_attrib = user_mail_attrib, user_mail_attrib=user_mail_attrib,
manage_groups = manage_groups, manage_groups=manage_groups,
allowed_groups = allowed_groups, allowed_groups=allowed_groups,
db = db): db=db):
if password == '': if password == '': # http://tools.ietf.org/html/rfc4513#section-5.1.2
logger.warning('blank password not allowed') logger.warning('blank password not allowed')
return False return False
logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s] manage_groups: [%s]' % ( logger.debug('mode: [%s] manage_user: [%s] custom_scope: [%s]'
str(mode), str(manage_user), str(custom_scope), str(manage_groups))) ' manage_groups: [%s]' % (str(mode), str(manage_user),
str(custom_scope), str(manage_groups)))
if manage_user: if manage_user:
if user_firstname_attrib.count(':') > 0: if user_firstname_attrib.count(':') > 0:
(user_firstname_attrib, user_firstname_part) = user_firstname_attrib.split(':', 1) (user_firstname_attrib, user_firstname_part) = user_firstname_attrib.split(':', 1)
@@ -205,9 +215,9 @@ def ldap_auth(server = 'ldap', port = None,
username = "%s@%s" % (username, '.'.join(domain)) username = "%s@%s" % (username, '.'.join(domain))
username_bare = username.split("@")[0] username_bare = username.split("@")[0]
con.set_option(ldap.OPT_PROTOCOL_VERSION, 3) con.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# In cases where ForestDnsZones and DomainDnsZones are found, # In cases where ForestDnsZones and DomainDnsZones are found,
# result will look like the following: # result will look like the following:
# ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com'] # ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com']
if ldap_binddn: if ldap_binddn:
# need to search directory with an admin account 1st # need to search directory with an admin account 1st
con.simple_bind_s(ldap_binddn, ldap_bindpw) con.simple_bind_s(ldap_binddn, ldap_bindpw)
@@ -219,22 +229,23 @@ def ldap_auth(server = 'ldap', port = None,
requested_attrs = ['sAMAccountName'] requested_attrs = ['sAMAccountName']
if manage_user: if manage_user:
requested_attrs.extend([user_firstname_attrib, requested_attrs.extend([user_firstname_attrib,
user_lastname_attrib, user_lastname_attrib,
user_mail_attrib]) user_mail_attrib])
result = con.search_ext_s( result = con.search_ext_s(
ldap_basedn, ldap.SCOPE_SUBTREE, ldap_basedn, ldap.SCOPE_SUBTREE,
"(&(sAMAccountName=%s)(%s))" % (ldap.filter.escape_filter_chars(username_bare), "(&(sAMAccountName=%s)(%s))" % (ldap.filter.escape_filter_chars(username_bare),
filterstr), filterstr),
requested_attrs)[0][1] requested_attrs)[0][1]
if not isinstance(result, dict): if not isinstance(result, dict):
# result should be a dict in the form {'sAMAccountName': [username_bare]} # result should be a dict in the form
# {'sAMAccountName': [username_bare]}
logger.warning('User [%s] not found!' % username) logger.warning('User [%s] not found!' % username)
return False return False
if ldap_binddn: if ldap_binddn:
# We know the user exists & is in the correct OU # We know the user exists & is in the correct OU
# so now we just check the password # so now we just check the password
con.simple_bind_s(username, password) con.simple_bind_s(username, password)
username=username_bare username = username_bare
if ldap_mode == 'domino': if ldap_mode == 'domino':
# Notes Domino # Notes Domino
@@ -244,34 +255,30 @@ def ldap_auth(server = 'ldap', port = None,
if manage_user: if manage_user:
# TODO: sorry I have no clue how to query attrs in domino # TODO: sorry I have no clue how to query attrs in domino
result = {user_firstname_attrib: username, result = {user_firstname_attrib: username,
user_lastname_attrib: None, user_lastname_attrib: None,
user_mail_attrib: None} user_mail_attrib: None}
if ldap_mode == 'cn': if ldap_mode == 'cn':
# OpenLDAP (CN) # OpenLDAP (CN)
dn = "cn=" + username + "," + ldap_basedn dn = "cn=" + username + "," + ldap_basedn
con.simple_bind_s(dn, password) con.simple_bind_s(dn, password)
if manage_user: if manage_user:
result = con.search_s( result = con.search_s(dn, ldap.SCOPE_BASE,
dn, ldap.SCOPE_BASE, "(objectClass=*)",
"(objectClass=*)", [user_firstname_attrib,
[user_firstname_attrib, user_lastname_attrib,
user_lastname_attrib, user_mail_attrib])[0][1]
user_mail_attrib]
)[0][1]
if ldap_mode == 'uid': if ldap_mode == 'uid':
# OpenLDAP (UID) # OpenLDAP (UID)
dn = "uid=" + username + "," + ldap_basedn dn = "uid=" + username + "," + ldap_basedn
con.simple_bind_s(dn, password) con.simple_bind_s(dn, password)
if manage_user: if manage_user:
result = con.search_s( result = con.search_s(dn, ldap.SCOPE_BASE,
dn, ldap.SCOPE_BASE, "(objectClass=*)",
"(objectClass=*)", [user_firstname_attrib,
[user_firstname_attrib, user_lastname_attrib,
user_lastname_attrib, user_mail_attrib])[0][1]
user_mail_attrib]
)[0][1]
if ldap_mode == 'company': if ldap_mode == 'company':
# no DNs or password needed to search directory # no DNs or password needed to search directory
@@ -280,18 +287,18 @@ def ldap_auth(server = 'ldap', port = None,
# bind anonymously # bind anonymously
con.simple_bind_s(dn, pw) con.simple_bind_s(dn, pw)
# search by e-mail address # search by e-mail address
filter = '(&(mail=' + ldap.filter.escape_filter_chars(username) + \ filter = '(&(mail=%s)(%s))' % (ldap.filter.escape_filter_chars(username),
')(' + filterstr + '))' filterstr)
# find the uid # find the uid
attrs = ['uid'] attrs = ['uid']
if manage_user: if manage_user:
attrs.extend([user_firstname_attrib, attrs.extend([user_firstname_attrib,
user_lastname_attrib, user_lastname_attrib,
user_mail_attrib]) user_mail_attrib])
# perform the actual search # perform the actual search
company_search_result = con.search_s(ldap_basedn, company_search_result = con.search_s(ldap_basedn,
ldap.SCOPE_SUBTREE, ldap.SCOPE_SUBTREE,
filter, attrs) filter, attrs)
dn = company_search_result[0][0] dn = company_search_result[0][0]
result = company_search_result[0][1] result = company_search_result[0][1]
# perform the real authentication test # perform the real authentication test
@@ -299,43 +306,47 @@ def ldap_auth(server = 'ldap', port = None,
if ldap_mode == 'uid_r': if ldap_mode == 'uid_r':
# OpenLDAP (UID) with subtree search and multiple DNs # OpenLDAP (UID) with subtree search and multiple DNs
if type(ldap_basedn) == type([]): if isinstance(ldap_basedn, list):
basedns = ldap_basedn basedns = ldap_basedn
else: else:
basedns = [ldap_basedn] basedns = [ldap_basedn]
filter = '(&(uid=%s)(%s))' % (ldap.filter.escape_filter_chars(username), filterstr) filter = '(&(uid=%s)(%s))' % (ldap.filter.escape_filter_chars(username), filterstr)
finded = False found = False
for basedn in basedns: for basedn in basedns:
try: try:
result = con.search_s(basedn, ldap.SCOPE_SUBTREE, filter) result = con.search_s(basedn, ldap.SCOPE_SUBTREE,
filter)
if result: if result:
user_dn = result[0][0] user_dn = result[0][0]
# Check the password # Check the password
con.simple_bind_s(user_dn, password) con.simple_bind_s(user_dn, password)
finded = True found = True
break break
except ldap.LDAPError, detail: except ldap.LDAPError, detail:
(exc_type, exc_value) = sys.exc_info()[:2] (exc_type, exc_value) = sys.exc_info()[:2]
logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" % logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" %
(basedn, filter, exc_type, exc_value)) (basedn, filter, exc_type, exc_value))
if not finded: if not found:
logger.warning('User [%s] not found!' % username) logger.warning('User [%s] not found!' % username)
return False return False
result = result[0][1] result = result[0][1]
if ldap_mode == 'custom': if ldap_mode == 'custom':
# OpenLDAP (username_attrs) with subtree search and multiple DNs # OpenLDAP (username_attrs) with subtree search and
if type(ldap_basedn) == type([]): # multiple DNs
if isinstance(ldap_basedn, list):
basedns = ldap_basedn basedns = ldap_basedn
else: else:
basedns = [ldap_basedn] basedns = [ldap_basedn]
filter = '(&(%s=%s)(%s))' % (username_attrib, ldap.filter.escape_filter_chars(username), filterstr) filter = '(&(%s=%s)(%s))' % (username_attrib,
ldap.filter.escape_filter_chars(username),
filterstr)
if custom_scope == 'subtree': if custom_scope == 'subtree':
ldap_scope = ldap.SCOPE_SUBTREE ldap_scope = ldap.SCOPE_SUBTREE
elif custom_scope == 'base': elif custom_scope == 'base':
ldap_scope = ldap.SCOPE_BASE ldap_scope = ldap.SCOPE_BASE
elif custom_scope == 'onelevel': elif custom_scope == 'onelevel':
ldap_scope = ldap.SCOPE_ONELEVEL ldap_scope = ldap.SCOPE_ONELEVEL
finded = False found = False
for basedn in basedns: for basedn in basedns:
try: try:
result = con.search_s(basedn, ldap_scope, filter) result = con.search_s(basedn, ldap_scope, filter)
@@ -343,27 +354,27 @@ def ldap_auth(server = 'ldap', port = None,
user_dn = result[0][0] user_dn = result[0][0]
# Check the password # Check the password
con.simple_bind_s(user_dn, password) con.simple_bind_s(user_dn, password)
finded = True found = True
break break
except ldap.LDAPError, detail: except ldap.LDAPError, detail:
(exc_type, exc_value) = sys.exc_info()[:2] (exc_type, exc_value) = sys.exc_info()[:2]
logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" % logger.warning("ldap_auth: searching %s for %s resulted in %s: %s\n" %
(basedn, filter, exc_type, exc_value)) (basedn, filter, exc_type, exc_value))
if not finded: if not found:
logger.warning('User [%s] not found!' % username) logger.warning('User [%s] not found!' % username)
return False return False
result = result[0][1] result = result[0][1]
if manage_user: if manage_user:
logger.info('[%s] Manage user data' % str(username)) logger.info('[%s] Manage user data' % str(username))
try: try:
if not user_firstname_part == None: if user_firstname_part is not None:
store_user_firstname = result[user_firstname_attrib][0].split(' ', 1)[user_firstname_part] store_user_firstname = result[user_firstname_attrib][0].split(' ', 1)[user_firstname_part]
else: else:
store_user_firstname = result[user_firstname_attrib][0] store_user_firstname = result[user_firstname_attrib][0]
except KeyError, e: except KeyError, e:
store_user_firstname = None store_user_firstname = None
try: try:
if not user_lastname_part == None: if user_lastname_part is not None:
store_user_lastname = result[user_lastname_attrib][0].split(' ', 1)[user_lastname_part] store_user_lastname = result[user_lastname_attrib][0].split(' ', 1)[user_lastname_part]
else: else:
store_user_lastname = result[user_lastname_attrib][0] store_user_lastname = result[user_lastname_attrib][0]
@@ -379,32 +390,30 @@ def ldap_auth(server = 'ldap', port = None,
# ################# # #################
user_in_db = db(db.auth_user.username == username) user_in_db = db(db.auth_user.username == username)
if user_in_db.count() > 0: if user_in_db.count() > 0:
user_in_db.update(first_name = store_user_firstname, user_in_db.update(first_name=store_user_firstname,
last_name = store_user_lastname, last_name=store_user_lastname,
email = store_user_mail) email=store_user_mail)
else: else:
db.auth_user.insert(first_name = store_user_firstname, db.auth_user.insert(first_name=store_user_firstname,
last_name = store_user_lastname, last_name=store_user_lastname,
email = store_user_mail, email=store_user_mail,
username = username) username=username)
except: except:
# #
# user as email # user as email
# ############## # ##############
user_in_db = db(db.auth_user.email == username) user_in_db = db(db.auth_user.email == username)
if user_in_db.count() > 0: if user_in_db.count() > 0:
user_in_db.update(first_name = store_user_firstname, user_in_db.update(first_name=store_user_firstname,
last_name = store_user_lastname, last_name=store_user_lastname)
)
else: else:
db.auth_user.insert(first_name = store_user_firstname, db.auth_user.insert(first_name=store_user_firstname,
last_name = store_user_lastname, last_name=store_user_lastname,
email = username email=username)
)
con.unbind() con.unbind()
if manage_groups: if manage_groups:
if not do_manage_groups(username,password): if not do_manage_groups(username, password):
return False return False
return True return True
except ldap.LDAPError, e: except ldap.LDAPError, e:
@@ -412,18 +421,18 @@ def ldap_auth(server = 'ldap', port = None,
logger.warning('[%s] Error in ldap processing' % str(username)) logger.warning('[%s] Error in ldap processing' % str(username))
logger.debug(traceback.format_exc()) logger.debug(traceback.format_exc())
return False return False
except IndexError, ex: # for AD membership test except IndexError, ex: # for AD membership test
import traceback import traceback
logger.warning('[%s] Ldap result indexing error' % str(username)) logger.warning('[%s] Ldap result indexing error' % str(username))
logger.debug(traceback.format_exc()) logger.debug(traceback.format_exc())
return False return False
def is_user_in_allowed_groups(username, def is_user_in_allowed_groups(username,
password = None, password=None,
allowed_groups = allowed_groups allowed_groups=allowed_groups):
):
""" """
Figure out if the username is a member of an allowed group in ldap or not Figure out if the username is a member of an allowed group
in ldap or not
""" """
# #
# Get all group name where the user is in actually in ldap # Get all group name where the user is in actually in ldap
@@ -441,12 +450,11 @@ def ldap_auth(server = 'ldap', port = None,
return False return False
def do_manage_groups(username, def do_manage_groups(username,
password = None, password=None,
db = db, db=db):
):
""" """
Manage user groups Manage user groups
Get all user's group from ldap and refresh the already stored Get all user's group from ldap and refresh the already stored
ones in web2py's application database or create new groups ones in web2py's application database or create new groups
according to ldap. according to ldap.
@@ -472,32 +480,35 @@ def ldap_auth(server = 'ldap', port = None,
# We create one # We create one
# ############################## # ##############################
try: try:
db_user_id = db.auth_user.insert(username = username, db_user_id = db.auth_user.insert(username=username,
first_name = username) first_name=username)
except AttributeError, e: except AttributeError, e:
db_user_id = db.auth_user.insert(email = username, db_user_id = db.auth_user.insert(email=username,
first_name = username) first_name=username)
if not db_user_id: if not db_user_id:
logging.error('There is no username or email for %s!' % username) logging.error('There is no username or email for %s!' % username)
raise raise
db_group_search = db((db.auth_membership.user_id == db_user_id) & \ db_group_search = db((db.auth_membership.user_id == db_user_id) &
(db.auth_user.id == db.auth_membership.user_id) & \ (db.auth_user.id == db.auth_membership.user_id) &
(db.auth_group.id == db.auth_membership.group_id)) (db.auth_group.id == db.auth_membership.group_id))
db_groups_of_the_user = list() db_groups_of_the_user = list()
db_group_id = dict() db_group_id = dict()
if db_group_search.count() > 0: if db_group_search.count() > 0:
for group in db_group_search.select(db.auth_group.id, db.auth_group.role, distinct = True): for group in db_group_search.select(db.auth_group.id,
db.auth_group.role,
distinct=True):
db_group_id[group.role] = group.id db_group_id[group.role] = group.id
db_groups_of_the_user.append(group.role) db_groups_of_the_user.append(group.role)
logging.debug('db groups of user %s: %s' % (username, str(db_groups_of_the_user))) logging.debug('db groups of user %s: %s' %
(username, str(db_groups_of_the_user)))
# #
# Delete user membership from groups where user is not anymore # Delete user membership from groups where user is not anymore
# ############################################################# # #############################################################
for group_to_del in db_groups_of_the_user: for group_to_del in db_groups_of_the_user:
if ldap_groups_of_the_user.count(group_to_del) == 0: if ldap_groups_of_the_user.count(group_to_del) == 0:
db((db.auth_membership.user_id == db_user_id) & \ db((db.auth_membership.user_id == db_user_id) &
(db.auth_membership.group_id == db_group_id[group_to_del])).delete() (db.auth_membership.group_id == db_group_id[group_to_del])).delete()
# #
@@ -506,32 +517,31 @@ def ldap_auth(server = 'ldap', port = None,
for group_to_add in ldap_groups_of_the_user: for group_to_add in ldap_groups_of_the_user:
if db_groups_of_the_user.count(group_to_add) == 0: if db_groups_of_the_user.count(group_to_add) == 0:
if db(db.auth_group.role == group_to_add).count() == 0: if db(db.auth_group.role == group_to_add).count() == 0:
gid = db.auth_group.insert(role = group_to_add, gid = db.auth_group.insert(role=group_to_add,
description = 'Generated from LDAP') description='Generated from LDAP')
else: else:
gid = db(db.auth_group.role == group_to_add).select(db.auth_group.id).first().id gid = db(db.auth_group.role == group_to_add).select(db.auth_group.id).first().id
db.auth_membership.insert(user_id = db_user_id, db.auth_membership.insert(user_id=db_user_id,
group_id = gid) group_id=gid)
except: except:
logger.warning("[%s] Groups are not managed successully!" % str(username)) logger.warning("[%s] Groups are not managed successfully!" %
str(username))
import traceback import traceback
logger.debug(traceback.format_exc()) logger.debug(traceback.format_exc())
return False return False
return True return True
def init_ldap( def init_ldap(ldap_server=server,
ldap_server = server, ldap_port=port,
ldap_port = port, ldap_basedn=base_dn,
ldap_basedn = base_dn, ldap_mode=mode,
ldap_mode = mode, secure=secure,
secure = secure, cert_path=cert_path,
cert_path = cert_path, cert_file=cert_file):
cert_file = cert_file
):
""" """
Inicialize ldap connection Inicialize ldap connection
""" """
logger.info('[%s] Inicialize ldap connection' % str(ldap_server)) logger.info('[%s] Initialize ldap connection' % str(ldap_server))
if secure: if secure:
if not ldap_port: if not ldap_port:
ldap_port = 636 ldap_port = 636
@@ -549,16 +559,15 @@ def ldap_auth(server = 'ldap', port = None,
return con return con
def get_user_groups_from_ldap(username, def get_user_groups_from_ldap(username,
password = None, password=None,
base_dn = base_dn, base_dn=base_dn,
ldap_binddn = bind_dn, ldap_binddn=bind_dn,
ldap_bindpw = bind_pw, ldap_bindpw=bind_pw,
group_dn = group_dn, group_dn=group_dn,
group_name_attrib = group_name_attrib, group_name_attrib=group_name_attrib,
group_member_attrib = group_member_attrib, group_member_attrib=group_member_attrib,
group_filterstr = group_filterstr, group_filterstr=group_filterstr,
ldap_mode = mode ldap_mode=mode):
):
""" """
Get all group names from ldap where the user is in Get all group names from ldap where the user is in
""" """
@@ -566,12 +575,12 @@ def ldap_auth(server = 'ldap', port = None,
# #
# Get all group name where the user is in actually in ldap # Get all group name where the user is in actually in ldap
# ######################################################### # #########################################################
# Inicialize ldap # Initialize ldap
if not group_dn: if not group_dn:
group_dn = base_dn group_dn = base_dn
con = init_ldap() con = init_ldap()
logger.debug('Username init: [%s]'%username) logger.debug('Username init: [%s]' % username)
if ldap_mode=='ad': if ldap_mode == 'ad':
# #
# Get the AD username # Get the AD username
# #################### # ####################
@@ -583,9 +592,9 @@ def ldap_auth(server = 'ldap', port = None,
username = "%s@%s" % (username, '.'.join(domain)) username = "%s@%s" % (username, '.'.join(domain))
username_bare = username.split("@")[0] username_bare = username.split("@")[0]
con.set_option(ldap.OPT_PROTOCOL_VERSION, 3) con.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
# In cases where ForestDnsZones and DomainDnsZones are found, # In cases where ForestDnsZones and DomainDnsZones are found,
# result will look like the following: # result will look like the following:
# ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com'] # ['ldap://ForestDnsZones.domain.com/DC=ForestDnsZones,DC=domain,DC=com']
if ldap_binddn: if ldap_binddn:
# need to search directory with an admin account 1st # need to search directory with an admin account 1st
con.simple_bind_s(ldap_binddn, ldap_bindpw) con.simple_bind_s(ldap_binddn, ldap_bindpw)
@@ -595,9 +604,9 @@ def ldap_auth(server = 'ldap', port = None,
con.simple_bind_s(username, password) con.simple_bind_s(username, password)
logger.debug('Ldap username connect...') logger.debug('Ldap username connect...')
# We have to use the full string # We have to use the full string
username = con.search_ext_s( username = con.search_ext_s(base_dn, ldap.SCOPE_SUBTREE,
base_dn, ldap.SCOPE_SUBTREE, "(&(sAMAccountName=%s)(%s))" %
"(&(sAMAccountName=%s)(%s))" % (ldap.filter.escape_filter_chars(username_bare), filterstr), ["cn"])[0][0] (ldap.filter.escape_filter_chars(username_bare), filterstr), ["cn"])[0][0]
else: else:
if ldap_binddn: if ldap_binddn:
# need to search directory with an bind_dn account 1st # need to search directory with an bind_dn account 1st
@@ -608,11 +617,11 @@ def ldap_auth(server = 'ldap', port = None,
# search for groups where user is in # search for groups where user is in
filter = '(&(%s=%s)(%s))' % (ldap.filter.escape_filter_chars(group_member_attrib), filter = '(&(%s=%s)(%s))' % (ldap.filter.escape_filter_chars(group_member_attrib),
ldap.filter.escape_filter_chars(username), ldap.filter.escape_filter_chars(username),
group_filterstr) group_filterstr)
group_search_result = con.search_s(group_dn, group_search_result = con.search_s(group_dn,
ldap.SCOPE_SUBTREE, ldap.SCOPE_SUBTREE,
filter, [group_name_attrib]) filter, [group_name_attrib])
ldap_groups_of_the_user = list() ldap_groups_of_the_user = list()
for group_row in group_search_result: for group_row in group_search_result:
group = group_row[1] group = group_row[1]
@@ -622,8 +631,6 @@ def ldap_auth(server = 'ldap', port = None,
logger.debug('User groups: %s' % ldap_groups_of_the_user) logger.debug('User groups: %s' % ldap_groups_of_the_user)
return list(ldap_groups_of_the_user) return list(ldap_groups_of_the_user)
if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax
if filterstr[0] == '(' and filterstr[-1] == ')': # rfc4515 syntax filterstr = filterstr[1:-1] # parens added again where used
filterstr = filterstr[1:-1] # parens added again where used
return ldap_auth_aux return ldap_auth_aux