Beispiel #1
0
    def test_match_dn_in_cursor(self):
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-1'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-2'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-3'))
        o = ObjectDef('inetOrgPerson')
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef(test_multivalued_attribute, 'Given Name')

        query_text = 'Common Name:=' + testcase_id + 'mat-*'
        r = Reader(self.connection, o, test_base, query_text)

        results = r.search()
        self.assertEqual(len(results), 3)

        e = r.match_dn('mat')  # multiple matches
        self.assertEqual(len(e), 3)
        e = r.match_dn(
            '-3'
        )  # single match. there's domains with -20xx in their names, so use -3 to match
        self.assertEqual(len(e), 1)
        e = r.match_dn('no-match')  # no match
        self.assertEqual(len(e), 0)
    def test_find_entry_with_text_index_match(self):
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-1'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-2'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'mat-3'))
        o = ObjectDef('inetOrgPerson')
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef(test_multivalued_attribute, 'Given Name')

        query_text = 'Common Name:=' + testcase_id + 'mat-*'
        r = Reader(self.connection, o, test_base, query_text)

        results = r.search()
        self.assertEqual(len(results), 3)
        try:  # multiple matches
            e = r['match']
        except KeyError:
            pass

        e = r['-2']  # exact match
        self.assertTrue('mat-2' in e.entry_dn)

        try:
            e = r['no-match']  # no match
        except KeyError:
            pass
    def test_search_with_None_default(self):
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-12'))

        ou = ObjectDef('inetOrgPerson')
        ou += AttrDef('cn', 'CommonName')
        ou += AttrDef('employeeType', key='Employee', default=None)
        qu = 'CommonName := ' + testcase_id + 'abs-12'
        ru = Reader(self.connection, ou, test_base, qu)
        lu = ru.search()
        self.assertEqual(lu[0].employee.value, None)
Beispiel #4
0
    def test_search_with_default(self):
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'abstract-member-10'))

        ou = ObjectDef('inetOrgPerson')
        ou += AttrDef('cn', 'CommonName')
        ou += AttrDef('employeeType', key='Employee', default='not employed')
        qu = 'CommonName := ' + testcase_id + 'abstract-member-10'
        ru = Reader(self.connection, ou, test_base, qu)
        lu = ru.search()
        self.assertEqual(str(lu[0].employee), 'not employed')
Beispiel #5
0
    def test_validate_query_filter(self):
        o = ObjectDef()
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef('givenName', 'Given Name')

        query_text = '|Common Name:=john;=Bob, Surname:=smith'
        r = Reader(self.connection, o, test_base, query_text)

        r._validate_query()

        self.assertEqual('Surname: =smith, |CommonName: =Bob;=john', r.validated_query)
    def test_create_query_filter(self):
        o = ObjectDef()
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef('givenName', 'Given Name')

        query_text = '|Common Name:=john;Bob, Surname:=smith'
        r = Reader(self.connection, o, test_base, query_text)

        r._create_query_filter()

        self.assertEqual('(&(sn=smith)(|(cn=Bob)(cn=john)))', r.query_filter)
Beispiel #7
0
    def test_search_with_dereference(self):
        reverse = lambda a, e: e[::-1]

        def raise_parentheses_rank(_, l):
            up = {'(': '[', ')': ']', '[': '{', ']': '}', '{': '<', '}': '>'}
            r = []
            for e in l:
                s = ''
                for c in e:
                    s += up[c] if c in up else c
                r.append(s)

            return r

        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'abstract-member-4'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'abstract-member-5'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'abstract-member-6'))
        self.delete_at_teardown.append(
            add_group(self.connection, testcase_id, 'abstract-group',
                      self.delete_at_teardown))
        ou = ObjectDef('inetOrgPerson')
        ou += AttrDef('cn', 'Common Name', post_query=reverse)
        ou += AttrDef('sn', 'Surname')
        ou += AttrDef('givenName',
                      'Given Name',
                      post_query=raise_parentheses_rank)
        ou += AttrDef('ACL')
        qu = 'Common Name: ' + testcase_id + 'abstract-member-*'
        ru = Reader(self.connection, ou, test_base, qu)
        lu = ru.search()
        self.assertEqual(len(lu), 3)

        og = ObjectDef('groupOfNames')
        og += AttrDef('member', dereference_dn=ou)
        og += 'cn'
        qg = 'cn := ' + testcase_id + 'abstract-group'
        rg = Reader(self.connection, og, test_base, qg)
        lg = rg.search()
        self.assertEqual(len(lg), 1)

        eg = lg[0]
        mg = eg.member
        self.assertEqual(len(mg), 3)
        ug = eg.member[0]
        self.assertTrue(
            str(ug.surname) in
            ['abstract-member-4', 'abstract-member-5', 'abstract-member-6'])
    def test_match_in_multiple_attribute(self):
        self.delete_at_teardown.append(
            add_user(self.connection,
                     testcase_id,
                     'mat-1',
                     attributes={
                         test_multivalued_attribute:
                         ['givenname-1', 'givenname-1a'],
                         'street':
                         '1a'
                     }))
        self.delete_at_teardown.append(
            add_user(self.connection,
                     testcase_id,
                     'mat-2',
                     attributes={
                         test_multivalued_attribute:
                         ['givenname-2', 'givenname-2a'],
                         'street':
                         '3a'
                     }))
        self.delete_at_teardown.append(
            add_user(self.connection,
                     testcase_id,
                     'mat-3',
                     attributes={
                         test_multivalued_attribute:
                         ['givenname-3', 'givenname-3a'],
                         'street':
                         '4a'
                     }))
        o = ObjectDef('inetOrgPerson')
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef(test_multivalued_attribute, 'Given Name')
        o += AttrDef('street', 'Street')

        query_text = 'Common Name:=' + testcase_id + 'mat-*'
        r = Reader(self.connection, o, test_base, query_text)

        results = r.search()
        self.assertEqual(len(results), 3)

        e = r.match(['Given Name', 'Street'], '3a')  # multiple matches
        self.assertEqual(len(e), 2)
        e = r.match(['Given Name', 'street'], '1a')  # single match
        self.assertEqual(len(e), 1)
        e = r.match(['Given Name', 'street'], 'no-match')  # no match
        self.assertEqual(len(e), 0)
    def test_search_filter_with_object_class(self):
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-1'))
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-2'))
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-3'))
        self.delete_at_teardown.append(add_group(self.connection, testcase_id, 'abs-grp', self.delete_at_teardown))
        reverse = lambda a, e: e[::-1]
        o = ObjectDef('inetOrgPerson')
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef(test_multivalued_attribute, 'Given Name', post_query=reverse)

        query_text = 'Common Name:=' + testcase_id + 'abs-*'
        r = Reader(self.connection, o, test_base, query_text)

        results = r.search()
        self.assertEqual(len(results), 3)
Beispiel #10
0
    def get_definition(self,
                       object_class: Union[str, List[str]],
                       attributes: Iterable[str] = None) -> ObjectDef:
        """
        Get a new object class definition automatically from LDAP Schema.
        object definitions are save as cache for later use in connection.
        :param object_class: The LDAP objectClass type to define
        :param attributes: Extra LDAP attributes to include
        :return: ldap3 ObjectDef instance
        """
        # create definition if missing
        if object_class not in self.definitions:
            with LogExecutionTime(
                    f"Loading LDAP Schema definition for objectClass {object_class}"
            ):
                self.definitions[object_class] = ObjectDef(
                    object_class, self.connection)

        # add missing attributes
        if attributes:
            for attr in attributes:
                if attr not in self.definitions[object_class]:
                    self.definitions[object_class] += AttrDef(attr)

        return self.definitions[object_class]
    def test_search_with_pre_query(self):
        change = lambda attr, value: testcase_id + 'abs-*'

        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-7'))
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-8'))
        self.delete_at_teardown.append(add_user(self.connection, testcase_id, 'abs-9'))
        self.delete_at_teardown.append(add_group(self.connection, testcase_id, 'abstract-group', self.delete_at_teardown))

        ou = ObjectDef('inetOrgPerson')
        ou += AttrDef('cn', 'Common Name', pre_query=change)
        ou += AttrDef('sn', 'Surname')
        ou += AttrDef(test_multivalued_attribute, 'Given Name')
        ou += AttrDef('ACL')
        qu = 'Common Name := bug'
        ru = Reader(self.connection, ou, test_base, qu)
        lu = ru.search()
        self.assertEqual(len(lu), 3)
    def test_create_query_filter_single_attribute_multiple_value(self):
        o = ObjectDef()
        o += AttrDef('cn', 'Common Name')

        query_text = '|Common Name:=john;=Bob'
        r = Reader(self.connection, o, test_base, query_text)

        r._create_query_filter()

        self.assertEqual('(|(cn=Bob)(cn=john))', r.query_filter)
    def test_create_query_filter_single_attribute_single_value(self):
        o = ObjectDef()
        o += AttrDef('cn', 'Common Name')

        query_text = 'Common Name:John'
        r = Reader(self.connection, o, test_base, query_text)

        r._create_query_filter()

        self.assertEqual('(cn=John)', r.query_filter)
Beispiel #14
0
    def __init__(self, server, group):
        self.server = server
        self.group = group

        self.obj = ObjectDef(['top', 'group'])
        self.obj += AttrDef('distinguishedName', key='dn')
        self.obj += AttrDef('objectClass', key='object_class')
        self.obj += AttrDef('cn', key='cn')
        self.obj += AttrDef('mail', key='email')
        self.obj += AttrDef('extensionName', key='email_canonical')
        self.obj += AttrDef('sAMAccountName', key='slug_name')
        self.obj += AttrDef('groupType', key='type')
        self.obj += AttrDef('flags', key='flags')
Beispiel #15
0
    def test_match_dn_in_cursor(self):
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'match-1'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'match-2'))
        self.delete_at_teardown.append(
            add_user(self.connection, testcase_id, 'match-3'))
        o = ObjectDef('inetOrgPerson')
        o += AttrDef('cn', 'Common Name')
        o += AttrDef('sn', 'Surname')
        o += AttrDef('givenName', 'Given Name')

        query_text = 'Common Name:=' + testcase_id + 'match-*'
        r = Reader(self.connection, o, test_base, query_text)

        results = r.search()
        self.assertEqual(len(results), 3)

        e = r.match_dn('match')  # multiple matches
        self.assertEqual(len(e), 3)
        e = r.match_dn('-2')  # single match
        self.assertEqual(len(e), 1)
        e = r.match_dn('no-match')  # no match
        self.assertEqual(len(e), 0)
Beispiel #16
0
 def test_modify_entry_with_attrdef_with_friendly_name(self):
     self.delete_at_teardown.append(
         add_user(self.connection,
                  testcase_id,
                  'new-9',
                  attributes={
                      test_multivalued_attribute:
                      testcase_id + 'friendly-attr-name-1'
                  }))
     a = AttrDef(name=test_multivalued_attribute, key='myname')
     o = ObjectDef('inetorgperson')
     o += a
     r = Reader(self.connection, o, test_base,
                'myname:=' + testcase_id + 'friendly*')
     r.search()
     self.assertTrue(r[0].myname, testcase_id + 'friendly-attr-name-1')
     w = Writer.from_cursor(r)
     e = w[0]
     e.myname += 'xyz'
     w.commit()
     self.assertTrue('xyz' in e.myname)
Beispiel #17
0
    def authenticate(self, request, ticket, service):
        """Verifies CAS ticket and gets or creates User object"""

        user = super(CASLDAPBackend,
                     self).authenticate(request, ticket, service)

        # Populate user attributes
        if user:
            try:
                server = Server(settings.LDAP_GROUPS_SERVER_URI)
                connection = Connection(
                    server=server,
                    auto_bind=True,
                    user=settings.LDAP_GROUPS_BIND_DN,
                    password=settings.LDAP_GROUPS_BIND_PASSWORD,
                    raise_exceptions=True)
                connection.start_tls()

                account_def = ObjectDef('user')
                account_def += AttrDef('userPrincipalName')
                account_def += AttrDef('displayName')
                account_def += AttrDef('givenName')
                account_def += AttrDef('sn')
                account_def += AttrDef('mail')

                account_reader = Reader(
                    connection=connection,
                    object_def=account_def,
                    query="userPrincipalName: {principal_name}".format(
                        principal_name=user.username),
                    base=settings.LDAP_GROUPS_BASE_DN)
                account_reader.search_subtree()

                user_info = account_reader.entries[0]
            except Exception as msg:
                logger.exception(msg,
                                 exc_info=True,
                                 extra={'request': request})
            else:
                principal_name = str(user_info["userPrincipalName"])
                username = principal_name.split("@")[0]

                user_group_objects = Reader(
                    connection=connection,
                    object_def=account_def,
                    query=
                    '(&(member=CN={username},OU=People,OU=Enterprise,OU=Accounts,DC=ad,DC=calpoly,DC=edu)(objectClass=group))'
                    .format(username=username),
                    base=settings.LDAP_GROUPS_BASE_DN).search()

                user_groups = []
                for group in user_group_objects:
                    user_groups.append(group.entry_dn)

                def AD_get_children(connection, parent):
                    connection.search(
                        settings.LDAP_GROUPS_BASE_DN,
                        "(&(objectCategory=group)(memberOf={group_name}))".
                        format(group_name=escape_query(parent)))
                    children = connection.entries
                    results = []
                    for child in children:
                        results.append(child.entry_dn)
                    return results

                def get_descendants(connection, parent):
                    descendants = []
                    queue = []
                    queue.append(parent)
                    visited = set()

                    while len(queue):
                        node = queue.pop()

                        if node not in visited:
                            children = AD_get_children(connection, node)
                            for child in children:
                                if child not in descendants:
                                    descendants.append(child)
                                    queue.append(child)
                            visited.add(node)

                    return descendants

                # New Code should use the ad_groups property of the user to enforce permissions
                user.ad_groups.clear()

                for group_id, group_dn in ADGroup.objects.all().values_list(
                        'id', 'distinguished_name'):
                    if group_dn in user_groups:
                        user.ad_groups.add(group_id)
                    else:
                        children = get_descendants(connection, group_dn)
                        for child in children:
                            if child in user_groups:
                                user.ad_groups.add(group_id)

                if not user.ad_groups.exists():
                    raise PermissionDenied(
                        'User %s is not in any of the allowed groups.' %
                        principal_name)

                if not user.ad_groups.all().filter(
                        distinguished_name=
                        'CN=UH-RN-DevTeam,OU=Technology,OU=UH,OU=Manual,OU=Groups,DC=ad,DC=calpoly,DC=edu'
                ).exists() and settings.RESTRICT_LOGIN_TO_DEVELOPERS:
                    raise PermissionDenied(
                        'Only developers can access the site on this server. Please use the primary site.'
                    )

                def get_group_members(group):
                    cache_key = 'group_members::' + (
                        group if " " not in group else group.replace(" ", "_"))
                    group_members = cache.get(cache_key)

                    if group_members is None:
                        try:
                            group_members = LDAPADGroup(
                                group).get_tree_members()
                        except InvalidGroupDN:
                            logger.exception(
                                'Could not retrieve group members for DN: ' +
                                group,
                                exc_info=True,
                                extra={'request': request})
                            return []

                        group_members = [
                            member["userPrincipalName"]
                            for member in group_members
                        ]
                        cache.set(cache_key, group_members, 60)

                    return group_members

                # Django Flags
                developer_list = get_group_members(
                    'CN=UH-RN-DevTeam,OU=Technology,OU=UH,OU=Manual,OU=Groups,DC=ad,DC=calpoly,DC=edu'
                )
                user.is_developer = principal_name in developer_list
                user.is_staff = principal_name in developer_list
                user.is_superuser = principal_name in developer_list

                user.full_name = user_info["displayName"]
                user.first_name = user_info["givenName"]
                user.last_name = user_info["sn"]
                user.email = user_info["mail"]

                user.save()

        return user
Beispiel #18
0
 def get_abstract_attr_def(self, key):
     return AttrDef(name=self.name,
                    key=key,
                    validate=self.validate,
                    default=self.default,
                    dereference_dn=self.dereference_dn)
Beispiel #19
0
    def authenticate(self, ticket, service, request):
        """Verifies CAS ticket and gets or creates User object"""

        user = super(CASLDAPBackend,
                     self).authenticate(ticket, service, request)

        # Populate user attributes
        if user:
            try:
                server = Server(settings.LDAP_GROUPS_SERVER_URI)
                connection = Connection(
                    server=server,
                    auto_bind=True,
                    user=settings.LDAP_GROUPS_BIND_DN,
                    password=settings.LDAP_GROUPS_BIND_PASSWORD,
                    raise_exceptions=True)
                connection.start_tls()

                account_def = ObjectDef('user')
                account_def.add(AttrDef('userPrincipalName'))
                account_def.add(AttrDef('displayName'))
                account_def.add(AttrDef('givenName'))
                account_def.add(AttrDef('sn'))
                account_def.add(AttrDef('mail'))

                account_reader = Reader(
                    connection=connection,
                    object_def=account_def,
                    query="userPrincipalName: {principal_name}".format(
                        principal_name=user.username),
                    base=settings.LDAP_GROUPS_BASE_DN)
                account_reader.search_subtree()

                user_info = account_reader.entries[0]
            except Exception as msg:
                logger.exception(msg,
                                 exc_info=True,
                                 extra={'request': request})
            else:
                principal_name = str(user_info["userPrincipalName"])

                def get_group_members(group):
                    cache_key = 'group_members::' + group
                    group_members = cache.get(cache_key)

                    if group_members is None:
                        try:
                            group_members = LDAPADGroup(
                                group).get_tree_members()
                        except InvalidGroupDN:
                            logger.exception(
                                'Could not retrieve group members for DN: ' +
                                group,
                                exc_info=True,
                                extra={'request': request})
                            return []

                        group_members = [
                            member["userPrincipalName"]
                            for member in group_members
                        ]
                        cache.set(cache_key, group_members, 60)

                    return group_members

                def check_group_for_user(group):
                    group_members = get_group_members(group.distinguished_name)
                    if principal_name in group_members:
                        user.ad_groups.add(group)

                # New Code should use the ad_groups property of the user to enforce permissions
                user.ad_groups.clear()
                with ThreadPoolExecutor(ADGroup.objects.count()) as pool:
                    pool.map(check_group_for_user, ADGroup.objects.all())

                if not user.ad_groups.exists():
                    raise PermissionDenied(
                        'User %s is not in any of the allowed groups.' %
                        principal_name)

                if not user.ad_groups.all().filter(
                        distinguished_name=
                        'CN=UH-RN-DevTeam,OU=Technology,OU=UH,OU=Manual,OU=Groups,DC=ad,DC=calpoly,DC=edu'
                ).exists() and settings.RESTRICT_LOGIN_TO_DEVELOPERS:
                    raise PermissionDenied(
                        'Only developers can access the site on this server. Please use the primary site.'
                    )

                # Django Flags
                developer_list = get_group_members(
                    'CN=UH-RN-DevTeam,OU=Technology,OU=UH,OU=Manual,OU=Groups,DC=ad,DC=calpoly,DC=edu'
                )
                user.is_developer = principal_name in developer_list
                user.is_staff = principal_name in developer_list
                user.is_superuser = principal_name in developer_list

                user.full_name = user_info["displayName"]
                user.first_name = user_info["givenName"]
                user.last_name = user_info["sn"]
                user.email = user_info["mail"]

                user.save()

        return user
Beispiel #20
0
    def __init__(self, server, user):
        self.server = server
        self.user = user

        self.person = ObjectDef(['top', 'organizationalPerson', 'user'])
        self.person += AttrDef('distinguishedName', key='dn')
        self.person += AttrDef('objectClass', key='object_class')
        self.person += AttrDef('cn', key='cn')
        self.person += AttrDef('sAMAccountName', key='username')
        self.person += AttrDef('givenName', key='first_name')
        self.person += AttrDef('sn', key='last_name')
        self.person += AttrDef('displayName', key='full_name')
        self.person += AttrDef('userPrincipalName', key='logon')
        self.person += AttrDef('mail', key='email')
        self.person += AttrDef('extensionName', key='email_canonical')
        self.person += AttrDef('userAccountControl', key='control')
        self.person += AttrDef('memberOf', key='groups')

        self.person += AttrDef(server.email_domain, key='email_domain')
        self.person += AttrDef(server.email_buzon_size, key='email_buzon_size')
        self.person += AttrDef(server.email_message_size,
                               key='email_message_size')

        self.person += AttrDef(server.internet_domain, key='internet_domain')
        self.person += AttrDef(server.internet_quota_type,
                               key='internet_quota_type')
        self.person += AttrDef(server.internet_quota_size,
                               key='internet_quota_size')
        self.person += AttrDef(server.internet_extra_quota_size,
                               key='internet_extra_quota_size')

        self.person += AttrDef(server.ftp_home, key='ftp_folder')
        self.person += AttrDef(server.ftp_size, key='ftp_size')

        self.query = 'username: {}'.format(self.user.username, )