79 |
79 |
# realm for selecting an ldap configuration or formatting usernames
|
80 |
80 |
'realm': 'ldap',
|
81 |
81 |
# template for building username
|
82 |
|
'username_template': '{username}@{realm}',
|
|
82 |
'username_template': '{uid}@{realm}',
|
83 |
83 |
# allow to match multiple user records
|
84 |
84 |
'multimatch': True,
|
85 |
85 |
# update username on all login, use with CAUTION !! only if you know that
|
... | ... | |
430 |
430 |
log.error('user bind failed: authz_id not found %r', ', '.join(authz_ids))
|
431 |
431 |
if block['replicas']:
|
432 |
432 |
break
|
433 |
|
return self._return_user(uri, authz_id, username, password, conn, block)
|
|
433 |
return self._return_user(uri, authz_id, password, conn, block)
|
434 |
434 |
except ldap.SERVER_DOWN:
|
435 |
435 |
log.error('ldap authentication error: %r is down', uri)
|
436 |
436 |
finally:
|
... | ... | |
456 |
456 |
def backend_name(self):
|
457 |
457 |
return '%s.%s' % (__name__, self.__class__.__name__)
|
458 |
458 |
|
459 |
|
def create_username(self, uri, dn, username, password, conn, block, attributes):
|
|
459 |
def create_username(self, uri, dn, conn, block, attributes):
|
460 |
460 |
'''Build a username using the configured template'''
|
461 |
461 |
username_template = unicode(block['username_template'])
|
462 |
|
return username_template.format(username=username, uri=uri,
|
|
462 |
# create the uid from user's dn
|
|
463 |
uid = dn.split(',')[0]
|
|
464 |
uid = uid.split('=')[1]
|
|
465 |
return username_template.format(uid=uid, uri=uri,
|
463 |
466 |
block=block, realm=block['realm'], **attributes)
|
464 |
467 |
|
465 |
468 |
def save_user(self, user, username):
|
... | ... | |
480 |
483 |
transaction.savepoint_rollback(sid)
|
481 |
484 |
username = u'{0}{1}@{2}'.format(left, i, right)
|
482 |
485 |
|
483 |
|
def populate_user_attributes(self, user, uri, dn, conn, block, attributes):
|
484 |
|
for legacy_attribute, legacy_field in (('email', 'email_field'),
|
|
486 |
def populate_user_attributes(self, user, block, attributes):
|
|
487 |
for legacy_attribute, legacy_field in (('email', 'email_field'),
|
485 |
488 |
('first_name', 'fname_field'), ('last_name', 'lname_field')):
|
486 |
489 |
ldap_attribute = block[legacy_field]
|
487 |
490 |
if not ldap_attribute:
|
... | ... | |
511 |
514 |
return True
|
512 |
515 |
return False
|
513 |
516 |
|
514 |
|
def populate_admin_flags_by_group(self, user, uri, dn, conn, block, group_dns):
|
|
517 |
def populate_admin_flags_by_group(self, user, block, group_dns):
|
515 |
518 |
'''Attribute admin flags based on groups.
|
516 |
519 |
|
517 |
520 |
It supersedes is_staff, is_superuser and is_active.'''
|
... | ... | |
526 |
529 |
else:
|
527 |
530 |
setattr(user, attr, False)
|
528 |
531 |
|
529 |
|
def populate_groups_by_mapping(self, user, uri, dn, conn, block, group_dns):
|
|
532 |
def populate_groups_by_mapping(self, user, dn, conn, block, group_dns):
|
530 |
533 |
'''Assign group to user based on a mapping from group DNs'''
|
531 |
534 |
group_mapping = block['group_mapping']
|
532 |
535 |
if not group_mapping:
|
... | ... | |
541 |
544 |
except KeyError:
|
542 |
545 |
pass
|
543 |
546 |
|
544 |
|
def get_ldap_group_dns(self, user, uri, dn, conn, block):
|
|
547 |
def get_ldap_group_dns(self, user, dn, conn, block):
|
545 |
548 |
'''Retrieve group DNs from the LDAP by attributes (memberOf) or by
|
546 |
549 |
filter.
|
547 |
550 |
'''
|
... | ... | |
565 |
568 |
group_dns.update(dn for dn, attributes in results)
|
566 |
569 |
return group_dns
|
567 |
570 |
|
568 |
|
def populate_user_groups(self, user, uri, dn, conn, block):
|
569 |
|
group_dns = self.get_ldap_group_dns(user, uri, dn, conn, block)
|
|
571 |
def populate_user_groups(self, user, dn, conn, block):
|
|
572 |
group_dns = self.get_ldap_group_dns(user, dn, conn, block)
|
570 |
573 |
log.debug('groups for dn %r: %r', dn, group_dns)
|
571 |
|
self.populate_admin_flags_by_group(user, uri, dn, conn, block, group_dns)
|
572 |
|
self.populate_groups_by_mapping(user, uri, dn, conn, block, group_dns)
|
|
574 |
self.populate_admin_flags_by_group(user, block, group_dns)
|
|
575 |
self.populate_groups_by_mapping(user, dn, conn, block, group_dns)
|
573 |
576 |
|
574 |
577 |
|
575 |
578 |
def get_group_by_name(self, block, group_name, create=None):
|
... | ... | |
585 |
588 |
except Group.DoesNotExist:
|
586 |
589 |
return None
|
587 |
590 |
|
588 |
|
def populate_mandatory_groups(self, user, uri, dn, conn, block):
|
|
591 |
def populate_mandatory_groups(self, user, block):
|
589 |
592 |
mandatory_groups = block.get('set_mandatory_groups')
|
590 |
593 |
if not mandatory_groups:
|
591 |
594 |
return
|
... | ... | |
594 |
597 |
if group:
|
595 |
598 |
user.groups.add(group)
|
596 |
599 |
|
597 |
|
def populate_admin_fields(self, user, uri, dn, conn, block):
|
|
600 |
def populate_admin_fields(self, user, block):
|
598 |
601 |
if block['is_staff'] is not None:
|
599 |
602 |
user.is_staff = block['is_staff']
|
600 |
603 |
if block['is_superuser'] is not None:
|
601 |
604 |
user.is_superuser = block['is_superuser']
|
602 |
605 |
|
603 |
|
def populate_user(self, user, uri, dn, username, conn, block, attributes):
|
604 |
|
self.update_user_identifiers(user, uri, dn, username, conn, block,
|
605 |
|
attributes)
|
606 |
|
self.populate_user_attributes(user, uri, dn, conn, block, attributes)
|
607 |
|
self.populate_admin_fields(user, uri, dn, conn, block)
|
608 |
|
self.populate_mandatory_groups(user, uri, dn, conn, block)
|
609 |
|
self.populate_user_groups(user, uri, dn, conn, block)
|
|
606 |
def populate_user(self, user, dn, username, conn, block, attributes):
|
|
607 |
self.update_user_identifiers(user, username, block, attributes)
|
|
608 |
self.populate_user_attributes(user, block, attributes)
|
|
609 |
self.populate_admin_fields(user, block)
|
|
610 |
self.populate_mandatory_groups(user, block)
|
|
611 |
self.populate_user_groups(user, dn, conn, block)
|
610 |
612 |
|
611 |
613 |
@classmethod
|
612 |
614 |
def attribute_name_from_external_id_tuple(cls, external_id_tuple):
|
... | ... | |
723 |
725 |
except User.DoesNotExist:
|
724 |
726 |
pass
|
725 |
727 |
|
726 |
|
def lookup_existing_user(self, uri, dn, username, password, conn, block, attributes):
|
|
728 |
def lookup_existing_user(self, username, block, attributes):
|
727 |
729 |
for lookup_type in block['lookups']:
|
728 |
730 |
if lookup_type == 'username':
|
729 |
731 |
return self.lookup_by_username(username)
|
730 |
732 |
elif lookup_type == 'external_id':
|
731 |
733 |
return self.lookup_by_external_id(block, attributes)
|
732 |
734 |
|
733 |
|
def update_user_identifiers(self, user, uri, dn, username, conn,
|
734 |
|
block, attributes):
|
|
735 |
def update_user_identifiers(self, user, username, block, attributes):
|
735 |
736 |
if block['transient']:
|
736 |
737 |
return
|
737 |
738 |
# if username has changed and we propagate those changes, update it
|
... | ... | |
762 |
763 |
.delete()
|
763 |
764 |
|
764 |
765 |
@commit_on_success
|
765 |
|
def _return_user(self, uri, dn, username, password, conn, block):
|
|
766 |
def _return_user(self, uri, dn, password, conn, block):
|
766 |
767 |
attributes = self.get_ldap_attributes(block, conn, dn)
|
767 |
768 |
if attributes is None:
|
768 |
769 |
# attributes retrieval failed
|
769 |
770 |
return
|
770 |
771 |
log.debug('retrieved attributes for %r: %r', dn, attributes)
|
771 |
|
username = self.create_username(uri, dn, username, password, conn,
|
772 |
|
block, attributes)
|
|
772 |
username = self.create_username(uri, dn, conn, block, attributes)
|
773 |
773 |
if block['transient']:
|
774 |
774 |
return self._return_transient_user(uri, dn, username, password,
|
775 |
775 |
conn, block, attributes)
|
... | ... | |
780 |
780 |
def _return_transient_user(self, uri, dn, username, password, conn, block, attributes):
|
781 |
781 |
user = LDAPUser(username=username)
|
782 |
782 |
user.ldap_init(block, dn, password, transient=True)
|
783 |
|
self.populate_user(user, uri, dn, username, conn, block, attributes)
|
|
783 |
self.populate_user(user, dn, username, conn, block, attributes)
|
784 |
784 |
user.pk = 'transient!{0}'.format(base64.b64encode(pickle.dumps(user)))
|
785 |
785 |
return user
|
786 |
786 |
|
787 |
787 |
def _return_django_user(self, uri, dn, username, password, conn, block, attributes):
|
788 |
|
user = self.lookup_existing_user(uri, dn, username, password, conn, block, attributes)
|
|
788 |
user = self.lookup_existing_user(username, block, attributes)
|
789 |
789 |
if user:
|
790 |
790 |
created = False
|
791 |
791 |
log.debug('found existing user %r', user)
|
... | ... | |
793 |
793 |
created = True
|
794 |
794 |
user = LDAPUser()
|
795 |
795 |
user.ldap_init(block, dn, password)
|
796 |
|
self.populate_user(user, uri, dn, username, conn, block, attributes)
|
|
796 |
self.populate_user(user, dn, username, conn, block, attributes)
|
797 |
797 |
if block['keep_password']:
|
798 |
798 |
if created:
|
799 |
799 |
user.set_password(password)
|