Example #1
0
def test_ldap_context(mocker, settings, options):
    warn = mocker.patch('flask_multipass.providers.ldap.util.warn')
    ldap_initialize = mocker.patch(
        'flask_multipass.providers.ldap.util.ReconnectLDAPObject')
    ldap_conn = MagicMock()
    ldap_initialize.return_value = ldap_conn
    with ldap_context(settings) as ldap_ctx:
        ldap_initialize.called_once_with(settings['uri'])
        assert ldap_conn.protocol_version == ldap.VERSION3, 'LDAP v3 has not been set'
        assert ldap_conn.set_option.mock_calls == [
            call.set_option(*args) for args in options
        ], 'Not all options set'
        if settings['starttls']:
            if urlparse(settings['uri']).scheme == 'ldaps':
                warn.assert_called_once_with(
                    'Unable to start TLS, LDAP connection already secured over SSL (LDAPS)'
                )
            else:
                ldap_conn.start_tls_s.assert_called_once_with()
        ldap_conn.simple_bind_s.assert_called_once_with(
            settings['bind_dn'], settings['bind_password'])
        assert current_ldap == ldap_ctx, 'The LDAP context has not been set as the current one'
        assert current_ldap == LDAPContext(connection=ldap_conn,
                                           settings=settings)
    ldap_conn.unbind_s.called_once()
    assert not current_ldap, 'The LDAP context has not been unset'
Example #2
0
 def search_identities(self, criteria, exact=False):
     with ldap_context(self.ldap_settings):
         search_filter = build_user_search_filter(criteria, self.settings['mapping'], exact=exact)
         if not search_filter:
             raise IdentityRetrievalFailed("Unable to generate search filter from criteria")
         for _, user_data in self._search_users(search_filter):
             yield IdentityInfo(self, identifier=user_data[self.ldap_settings['uid']][0], **to_unicode(user_data))
Example #3
0
 def search_groups(self, name, exact=False):
     with ldap_context(self.ldap_settings):
         search_filter = build_group_search_filter({self.ldap_settings['gid']: {name}}, exact=exact)
         if not search_filter:
             raise GroupRetrievalFailed("Unable to generate search filter from criteria")
         for group_dn, group_data in self._search_groups(search_filter):
             yield self.group_class(self, group_data.get(self.ldap_settings['gid'])[0], group_dn)
Example #4
0
 def _get_identity(self, identifier):
     with ldap_context(self.ldap_settings):
         user_dn, user_data = get_user_by_id(identifier, self._attributes)
     if not user_dn:
         return None
     return IdentityInfo(self,
                         identifier=user_data[self.ldap_settings['uid']][0],
                         **to_unicode(user_data))
Example #5
0
 def get_group(self, name):
     with ldap_context(self.ldap_settings):
         group_dn, group_data = get_group_by_id(name,
                                                [self.ldap_settings['gid']])
     if not group_dn:
         return None
     group_name = to_unicode(group_data[self.ldap_settings['gid']][0])
     return self.group_class(self, group_name, group_dn)
Example #6
0
 def get_group(self, name):
     with ldap_context(self.ldap_settings):
         group_dn, group_data = get_group_by_id(name,
                                                [self.ldap_settings['gid']])
     if not group_dn:
         return None
     return self.group_class(self,
                             group_data.get(self.ldap_settings['gid'])[0],
                             group_dn)
def test_search_none_existing_entry(mocker, settings, base_dn, search_filter, attributes, msg_ids):
    page_ctrl = MagicMock()
    mocker.patch('flask_multipass.providers.ldap.operations.SimplePagedResultsControl', return_value=page_ctrl)
    ldap_connection = MagicMock(result3=MagicMock(side_effect=NO_SUCH_OBJECT),
                                search_ext=MagicMock(side_effect=msg_ids))
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject', return_value=ldap_connection)

    with ldap_context(settings):
        for result in search(base_dn, search_filter, attributes):
            pytest.fail('search should not yield any result')
Example #8
0
 def search_groups(self, name, exact=False):
     with ldap_context(self.ldap_settings):
         search_filter = build_group_search_filter(
             {self.ldap_settings['gid']: {name}}, exact=exact)
         if not search_filter:
             raise GroupRetrievalFailed(
                 "Unable to generate search filter from criteria")
         for group_dn, group_data in self._search_groups(search_filter):
             yield self.group_class(
                 self,
                 group_data.get(self.ldap_settings['gid'])[0], group_dn)
Example #9
0
 def get_members(self):
     with ldap_context(self.ldap_settings):
         group_dns = self._iter_group()
         group_dn = next(group_dns)
         while group_dn:
             user_filter = build_user_search_filter({self.ldap_settings['member_of_attr']: {group_dn}}, exact=True)
             for _, user_data in self.provider._search_users(user_filter):
                 yield IdentityInfo(self.provider, identifier=user_data[self.ldap_settings['uid']][0],
                                    **to_unicode(user_data))
             group_filter = build_group_search_filter({self.ldap_settings['member_of_attr']: {group_dn}}, exact=True)
             subgroups = list(self.provider._search_groups(group_filter))
             group_dn = group_dns.send(subgroups)
Example #10
0
 def search_groups(self, name, exact=False):
     with ldap_context(self.ldap_settings):
         search_filter = build_group_search_filter(
             {self.ldap_settings['gid']: {name}}, exact=exact)
         if not search_filter:
             raise GroupRetrievalFailed(
                 "Unable to generate search filter from criteria",
                 provider=self)
         for group_dn, group_data in self._search_groups(search_filter):
             group_name = to_unicode(
                 group_data[self.ldap_settings['gid']][0])
             yield self.group_class(self, group_name, group_dn)
Example #11
0
 def has_member(self, user_identifier):
     with ldap_context(self.ldap_settings):
         user_dn, user_data = get_user_by_id(user_identifier, attributes=[self.ldap_settings['member_of_attr']])
         if not user_dn:
             return False
         if self.ldap_settings['ad_group_style']:
             group_dn, group_data = get_group_by_id(self.name, attributes=['objectSid'])
             group_sids = group_data.get('objectSid')
             token_groups = get_token_groups_from_user_dn(user_dn)
             return any(group_sid in token_groups for group_sid in group_sids)
         else:
             return self.dn in user_data.get(self.ldap_settings['member_of_attr'], [])
Example #12
0
 def search_identities(self, criteria, exact=False):
     with ldap_context(self.ldap_settings):
         search_filter = build_user_search_filter(criteria,
                                                  self.settings['mapping'],
                                                  exact=exact)
         if not search_filter:
             raise IdentityRetrievalFailed(
                 "Unable to generate search filter from criteria")
         for _, user_data in self._search_users(search_filter):
             yield IdentityInfo(
                 self,
                 identifier=user_data[self.ldap_settings['uid']][0],
                 **to_unicode(user_data))
Example #13
0
 def process_local_login(self, data):
     username = data['username']
     password = data['password']
     with ldap_context(self.ldap_settings, use_cache=False):
         try:
             user_dn, user_data = get_user_by_id(username, attributes=[self.ldap_settings['uid']])
             if not user_dn:
                 raise NoSuchUser
             current_ldap.connection.simple_bind_s(user_dn, password)
         except INVALID_CREDENTIALS:
             raise InvalidCredentials
     auth_info = AuthInfo(self, identifier=user_data[self.ldap_settings['uid']][0])
     return self.multipass.handle_auth_success(auth_info)
Example #14
0
def test_search(mocker, settings, base_dn, search_filter, attributes, mock_data, expected):
    mock_data['cookies'].append('')  # last search operation should not return a cookie
    page_ctrl = MagicMock()
    mocker.patch('flask_multipass.providers.ldap.operations.SimplePagedResultsControl', return_value=page_ctrl)
    ldap_connection = MagicMock(result3=MagicMock(side_effect=((None, entries, None, [page_ctrl])
                                                               for entries in mock_data['results'])),
                                search_ext=MagicMock(side_effect=mock_data['msg_ids']))
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject', return_value=ldap_connection)
    mocker.patch('flask_multipass.providers.ldap.operations.get_page_cookie', side_effect=mock_data['cookies'])

    with ldap_context(settings):
        for i, result in enumerate(search(base_dn, search_filter, attributes)):
            assert result == expected[i]
Example #15
0
def test_search_none_existing_entry(mocker, settings, base_dn, search_filter,
                                    attributes, msg_ids):
    page_ctrl = MagicMock()
    mocker.patch(
        'flask_multipass.providers.ldap.operations.SimplePagedResultsControl',
        return_value=page_ctrl)
    ldap_connection = MagicMock(result3=MagicMock(side_effect=NO_SUCH_OBJECT),
                                search_ext=MagicMock(side_effect=msg_ids))
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject',
                 return_value=ldap_connection)

    with ldap_context(settings):
        for result in search(base_dn, search_filter, attributes):
            pytest.fail('search should not yield any result')
Example #16
0
 def process_local_login(self, data):
     username = data['username']
     password = data['password']
     with ldap_context(self.ldap_settings, use_cache=False):
         try:
             user_dn, user_data = get_user_by_id(
                 username, attributes=[self.ldap_settings['uid']])
             if not user_dn:
                 raise NoSuchUser(provider=self)
             current_ldap.connection.simple_bind_s(user_dn, password)
         except INVALID_CREDENTIALS:
             raise InvalidCredentials(provider=self)
     auth_info = AuthInfo(
         self, identifier=user_data[self.ldap_settings['uid']][0])
     return self.multipass.handle_auth_success(auth_info)
Example #17
0
def test_find_one(mocker, base_dn, search_filter, data, expected):
    settings = {
        'uri': 'ldaps://ldap.example.com:636',
        'bind_dn': 'uid=admin,DC=example,DC=com',
        'bind_password': '******',
        'verify_cert': True,
        'starttls': True,
        'timeout': 10
    }

    ldap_search = MagicMock(return_value=data)
    ldap_conn = MagicMock(search_ext_s=ldap_search)
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject', return_value=ldap_conn)

    with ldap_context(settings):
        assert find_one(base_dn, search_filter) == expected
Example #18
0
 def has_member(self, user_identifier):
     with ldap_context(self.ldap_settings):
         user_dn, user_data = get_user_by_id(
             user_identifier,
             attributes=[self.ldap_settings['member_of_attr']])
         if not user_dn:
             return False
         if self.ldap_settings['ad_group_style']:
             group_dn, group_data = get_group_by_id(
                 self.name, attributes=['objectSid'])
             group_sids = group_data.get('objectSid')
             token_groups = get_token_groups_from_user_dn(user_dn)
             return any(group_sid in token_groups
                        for group_sid in group_sids)
         else:
             return self.dn in user_data.get(
                 self.ldap_settings['member_of_attr'], [])
Example #19
0
 def get_members(self):
     with ldap_context(self.ldap_settings):
         group_dns = self._iter_group()
         group_dn = next(group_dns)
         while group_dn:
             user_filter = build_user_search_filter(
                 {self.ldap_settings['member_of_attr']: {group_dn}},
                 exact=True)
             for _, user_data in self.provider._search_users(user_filter):
                 yield IdentityInfo(
                     self.provider,
                     identifier=user_data[self.ldap_settings['uid']][0],
                     **to_unicode(user_data))
             group_filter = build_group_search_filter(
                 {self.ldap_settings['member_of_attr']: {group_dn}},
                 exact=True)
             subgroups = list(self.provider._search_groups(group_filter))
             group_dn = group_dns.send(subgroups)
Example #20
0
def test_ldap_context_invalid_credentials(mocker, method, triggered_exception, caught_exception, message):
    settings = {
        'uri': 'ldaps://ldap.example.com:636',
        'bind_dn': 'uid=admin,DC=example,DC=com',
        'bind_password': '******',
        'verify_cert': True,
        'starttls': True
    }

    ldap_initialize = mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject')
    ldap_conn = MagicMock()
    getattr(ldap_conn, method).side_effect = triggered_exception
    ldap_initialize.return_value = ldap_conn

    with pytest.raises(caught_exception) as excinfo:
        with ldap_context(settings):
            current_ldap.connection.search_s('dc=example,dc=com', ldap.SCOPE_SUBTREE)
    assert excinfo.value.message == message
Example #21
0
def test_get_token_groups_from_user_dn(mocker, user_dn, mock_data, expected):
    settings = {
        'uri': 'ldaps://ldap.example.com:636',
        'bind_dn': 'uid=admin,DC=example,DC=com',
        'bind_password': '******',
        'verify_cert': True,
        'cert_file': ' /etc/ssl/certs/ca-certificates.crt',
        'starttls': True,
        'timeout': 10
    }

    ldap_search = MagicMock(return_value=mock_data)
    ldap_conn = MagicMock(search_ext_s=ldap_search)
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject', return_value=ldap_conn)
    with ldap_context(settings):
        assert get_token_groups_from_user_dn(user_dn) == expected
        # Token-Groups must be retrieved from a base scope query
        ldap_search.assert_called_once_with(user_dn, SCOPE_BASE, sizelimit=1, timeout=settings['timeout'],
                                            attrlist=['tokenGroups'])
Example #22
0
def test_ldap_context(mocker, settings, options):
    warn = mocker.patch('flask_multipass.providers.ldap.util.warn')
    ldap_initialize = mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject')
    ldap_conn = MagicMock()
    ldap_initialize.return_value = ldap_conn
    with ldap_context(settings) as ldap_ctx:
        ldap_initialize.called_once_with(settings['uri'])
        assert ldap_conn.protocol_version == ldap.VERSION3, 'LDAP v3 has not been set'
        assert ldap_conn.set_option.mock_calls == [call.set_option(*args) for args in options], 'Not all options set'
        if settings['starttls']:
            if urlparse(settings['uri']).scheme == 'ldaps':
                warn.assert_called_once_with('Unable to start TLS, LDAP connection already secured over SSL (LDAPS)')
            else:
                ldap_conn.start_tls_s.assert_called_once()
        ldap_conn.simple_bind_s.assert_called_once_with(settings['bind_dn'], settings['bind_password'])
        assert current_ldap == ldap_ctx, 'The LDAP context has not been set as the current one'
        assert current_ldap == LDAPContext(connection=ldap_conn, settings=settings)
    ldap_conn.unbind_s.called_once()
    assert not current_ldap, 'The LDAP context has not been unset'
Example #23
0
def test_search(mocker, settings, base_dn, search_filter, attributes,
                mock_data, expected):
    mock_data['cookies'].append(
        '')  # last search operation should not return a cookie
    page_ctrl = MagicMock()
    mocker.patch(
        'flask_multipass.providers.ldap.operations.SimplePagedResultsControl',
        return_value=page_ctrl)
    ldap_connection = MagicMock(
        result3=MagicMock(side_effect=((None, entries, None, [page_ctrl])
                                       for entries in mock_data['results'])),
        search_ext=MagicMock(side_effect=mock_data['msg_ids']))
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject',
                 return_value=ldap_connection)
    mocker.patch('flask_multipass.providers.ldap.operations.get_page_cookie',
                 side_effect=mock_data['cookies'])

    with ldap_context(settings):
        for i, result in enumerate(search(base_dn, search_filter, attributes)):
            assert result == expected[i]
Example #24
0
 def get_identity_groups(self, identifier):
     groups = set()
     with ldap_context(self.ldap_settings):
         user_dn, user_data = get_user_by_id(identifier, self._attributes)
         if not user_dn:
             return set()
         if self.ldap_settings['ad_group_style']:
             for sid in get_token_groups_from_user_dn(user_dn):
                 search_filter = build_group_search_filter(
                     {'objectSid': {sid}}, exact=True)
                 for group_dn, group_data in self._search_groups(
                         search_filter):
                     group_name = to_unicode(
                         group_data[self.ldap_settings['gid']][0])
                     groups.add(self.group_class(self, group_name,
                                                 group_dn))
         else:
             # OpenLDAP does not have a way to get all groups for a user including nested ones
             raise NotImplementedError(
                 'Only available for active directory')
     return groups
Example #25
0
def test_get_token_groups_from_user_dn(mocker, user_dn, mock_data, expected):
    settings = {
        'uri': 'ldaps://ldap.example.com:636',
        'bind_dn': 'uid=admin,DC=example,DC=com',
        'bind_password': '******',
        'verify_cert': True,
        'starttls': True,
        'timeout': 10
    }

    ldap_search = MagicMock(return_value=mock_data)
    ldap_conn = MagicMock(search_ext_s=ldap_search)
    mocker.patch('flask_multipass.providers.ldap.util.ReconnectLDAPObject',
                 return_value=ldap_conn)
    with ldap_context(settings):
        assert get_token_groups_from_user_dn(user_dn) == expected
        # Token-Groups must be retrieved from a base scope query
        ldap_search.assert_called_once_with(user_dn,
                                            SCOPE_BASE,
                                            sizelimit=1,
                                            timeout=settings['timeout'],
                                            attrlist=['tokenGroups'])
Example #26
0
 def _get_identity(self, identifier):
     with ldap_context(self.ldap_settings):
         user_dn, user_data = get_user_by_id(identifier, self._attributes)
     if not user_dn:
         return None
     return IdentityInfo(self, identifier=user_data[self.ldap_settings['uid']][0], **to_unicode(user_data))
Example #27
0
 def get_group(self, name):
     with ldap_context(self.ldap_settings):
         group_dn, group_data = get_group_by_id(name, [self.ldap_settings['gid']])
     if not group_dn:
         return None
     return self.group_class(self, group_data.get(self.ldap_settings['gid'])[0], group_dn)