Commit 20758843 by Czémán Arnold

dashboard: Extend org id support in ldap authentication

parent 31419716
......@@ -602,10 +602,13 @@ if get_env_variable('LDAP_AUTH', 'FALSE') == 'TRUE':
"ONELEVEL": ldap.SCOPE_SUBTREE,
}
LDAP_GROUP_MEMBER_ATTRIBUTE = (
get_env_variable("LDAP_GROUP_MEMBER_ATTRIBUTE", "member"))
LDAP_GROUP_MAP = {
"POSIX": PosixGroupType(),
"NIS": NISGroupType(),
"MEMBER_DN": MemberDNGroupType(),
"MEMBER_DN": MemberDNGroupType(LDAP_GROUP_MEMBER_ATTRIBUTE),
"GROUP_OF_NAMES": GroupOfNamesType(),
"GROUP_OF_UNIQUE_NAMES": GroupOfUniqueNamesType(),
"AD": ActiveDirectoryGroupType(),
......@@ -659,5 +662,11 @@ if get_env_variable('LDAP_AUTH', 'FALSE') == 'TRUE':
LDAP_ORG_ID_ATTRIBUTE = (
get_env_variable("LDAP_ORG_ID_ATTRIBUTE", "") == "TRUE")
LDAP_USER_ORG_ID_ATTRIBUTE = (
get_env_variable("LDAP_USER_ORG_ID_ATTRIBUTE", "DN"))
LDAP_GROUP_ORG_ID_ATTRIBUTE = (
get_env_variable("LDAP_GROUP_ORG_ID_ATTRIBUTE", "DN"))
LDAP_GROUP_OWNER_ATTRIBUTE = get_env_variable("LDAP_GROUP_OWNER_ATTRIBUTE",
"owner")
......@@ -35,64 +35,107 @@ def ldap_connect():
return conn
def get_group(conn, group_dn):
group = LDAPSearch(group_dn, ldap.SCOPE_BASE, "cn=*").execute(conn)
if len(group) == 0:
return None
return group[0][1]
def get_group_org_id(conn, group_dn):
group_org_id_attr = settings.LDAP_GROUP_ORG_ID_ATTRIBUTE
if group_org_id_attr == "DN":
return group_dn.upper()
else:
group = get_group(conn, group_dn)
if group is None:
logger.error("LDAP communication error, "
"while query group object.")
return None
group_org_id = group.get(group_org_id_attr)
if group_org_id is None:
logger.error("Group org id attribute '%s' does not exist!",
group_org_id_attr)
return None
return group_org_id[0].upper()
def get_user_org_id(ldap_user):
user_org_id_attr = settings.LDAP_USER_ORG_ID_ATTRIBUTE
if user_org_id_attr == "DN":
return ldap_user.dn.upper()
else:
user_org_id = ldap_user.attrs.get(user_org_id_attr)
if user_org_id is None:
logger.error("User org id attribute '%s' does not exist!",
user_org_id_attr)
return user_org_id[0]
def owns(conn, user_dn, group_dn):
ownerattr = settings.LDAP_GROUP_OWNER_ATTRIBUTE
group = LDAPSearch(group_dn.lower(), ldap.SCOPE_BASE, "cn=*").execute(conn)
if len(group) == 0:
group = get_group(conn, group_dn)
if group is None:
return False
group = group[0]
owners = group[1].get(ownerattr, [])
logger.error(owners)
return user_dn in map(unicode.upper, owners)
owners = group.get(ownerattr, [])
return user_dn in owners
def ldap_save_org_id(sender, user, ldap_user, **kwargs):
logger.debug("ldap_save_org_id called by %s", user.username)
user_dn = ldap_user.dn.upper()
user_org_id = get_user_org_id(ldap_user)
if user_org_id is None:
return
if user.pk is None:
user.save()
logger.debug("ldap_save_org_id saved user %s", unicode(user))
profile, created = Profile.objects.get_or_create(user=user)
if created or profile.org_id != user_dn:
if created or profile.org_id != user_org_id:
logger.info("org_id of %s added to user %s's profile",
user_dn, user.username)
profile.org_id = user_dn
user_org_id, user.username)
profile.org_id = user_org_id
profile.save()
else:
logger.debug("org_id of %s already added to user %s's profile",
user_dn, user.username)
user_org_id, user.username)
group_dns = map(unicode.upper, ldap_user.group_dns)
for group in group_dns:
# connection will close, when object destroys
# https://www.python-ldap.org/doc/html/ldap.html#ldap-objects
conn = ldap_connect()
for group_dn in ldap_user.group_dns:
group_org_id = get_group_org_id(conn, group_dn)
if group_org_id is None:
continue
try:
g = GroupProfile.search(group)
g = GroupProfile.search(group_org_id)
except Group.DoesNotExist:
logger.debug('cant find membergroup %s', group)
logger.debug('cant find membergroup %s', group_org_id)
else:
logger.debug('could find membergroup %s (%s)',
group, unicode(g))
group_org_id, unicode(g))
g.user_set.add(user)
for i in FutureMember.objects.filter(org_id__iexact=user_dn):
for i in FutureMember.objects.filter(org_id__iexact=user_org_id):
i.group.user_set.add(user)
i.delete()
# connection will close, when object destroys
# https://www.python-ldap.org/doc/html/ldap.html#ldap-objects
conn = ldap_connect()
for group in group_dns:
for group_dn in ldap_user.group_dns:
group_org_id = get_group_org_id(conn, group_dn)
if group_org_id is None:
continue
try:
g = GroupProfile.search(group)
g = GroupProfile.search(group_org_id)
except Group.DoesNotExist:
logger.debug('cant find ownergroup %s', group)
logger.debug('cant find ownergroup %s', group_org_id)
else:
if owns(conn, user_dn, group):
if owns(conn, ldap_user.dn, group_dn):
logger.debug('could find ownergroup %s (%s)',
group, unicode(g))
group_org_id, unicode(g))
g.profile.set_level(user, 'owner')
else:
logger.debug('cant find ownergroup %s', group)
logger.debug('cant find ownergroup %s', group_org_id)
return False # User did not change
......@@ -175,7 +175,7 @@ class Profile(Model):
max_length=32,
default=settings.LANGUAGE_CODE, blank=False)
org_id = CharField( # may be populated from eduPersonOrgId field
unique=True, blank=True, null=True, max_length=64,
unique=True, blank=True, null=True, max_length=255,
help_text=_('Unique identifier of the person, e.g. a student number.'))
instance_limit = IntegerField(default=5)
use_gravatar = BooleanField(
......
......@@ -82,22 +82,23 @@ class GroupCodeMixin(object):
newgroups.append(group)
if ldap_available:
from ..ldap_utils import owns, ldap_connect, get_group_org_id
ldap_user = getattr(request.user, "ldap_user", None)
if ldap_user is None:
return newgroups
from ..ldap_utils import owns, ldap_connect
user_dn = ldap_user.dn.upper()
group_dns = map(unicode.upper, ldap_user.group_dns)
user_dn = ldap_user.dn
# connection will close, when object destroys
# https://www.python-ldap.org/doc/html/ldap.html#ldap-objects
conn = ldap_connect()
for group in group_dns:
for group_dn in ldap_user.group_dns:
group_org_id = get_group_org_id(conn, group_dn)
if group_org_id is None:
continue
try:
GroupProfile.search(group)
GroupProfile.search(group_org_id)
except Group.DoesNotExist:
if owns(conn, user_dn, group):
newgroups.append(group)
if owns(conn, user_dn, group_dn):
newgroups.append(group_org_id)
return newgroups
......
......@@ -58,7 +58,7 @@ from ..forms import TransferOwnershipForm
logger = logging.getLogger(__name__)
saml_available = hasattr(settings, "SAML_CONFIG")
ldap_available = hasattr(settings, "AUTH_LDAP_SERVER_URI")
ldap_available = getattr(settings, "LDAP_ORG_ID_ATTRIBUTE", False)
def external_auth_available():
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment