def test_null_port(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, port=None) self.assertEqual(389, backend._port) backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, port=None, use_ssl=True) self.assertEqual(LDAPS_PORT, backend._port) backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, port=9090, use_ssl=True) self.assertEqual(9090, backend._port)
def test_authenticatefailure_non_group_member_non_required_group(self): # User is member of a group which is not required backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='and') authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated) backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='or') authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated)
def test_authenticate_and_get_user_groups_caching_enabled(self): required_group_dns = ['cn=group1,dc=stackstorm,dc=net'] backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='or', cache_user_groups_response=True) self.assertEqual(ldap.ldapobject.SimpleLDAPObject.search_s.call_count, 0) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertTrue(authenticated) self.assertEqual(ldap.ldapobject.SimpleLDAPObject.search_s.call_count, 2) user_groups = backend.get_user_groups(username=LDAP_USER_UID) self.assertEqual(user_groups, ['cn=group1,dc=stackstorm,dc=net']) self.assertEqual(ldap.ldapobject.SimpleLDAPObject.search_s.call_count, 2) self.assertTrue(LDAP_USER_UID in backend._user_groups_cache)
def test_get_groups_caching_cache_ttl(self): required_group_dns = [ 'cn=group3,dc=stackstorm,dc=net', 'cn=group4,dc=stackstorm,dc=net' ] backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='or', cache_user_groups_response=True, cache_user_groups_cache_ttl=1) user_groups = backend.get_user_groups(username=LDAP_USER_UID) self.assertEqual(user_groups, ['cn=group3,dc=stackstorm,dc=net']) self.assertTrue(LDAP_USER_UID in backend._user_groups_cache) self.assertEqual(backend._user_groups_cache[LDAP_USER_UID], ['cn=group3,dc=stackstorm,dc=net']) # After 1 second, cache entry should expire and it should result in another search_s call # which returns group4 time.sleep(1.5) user_groups = backend.get_user_groups(username=LDAP_USER_UID) self.assertEqual(user_groups, ['cn=group4,dc=stackstorm,dc=net']) self.assertTrue(LDAP_USER_UID in backend._user_groups_cache) self.assertEqual(backend._user_groups_cache[LDAP_USER_UID], ['cn=group4,dc=stackstorm,dc=net']) # Cache should now be empty time.sleep(1.5) self.assertFalse(LDAP_USER_UID in backend._user_groups_cache)
def test_and_is_default_group_dns_check_value(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) self.assertEqual(backend._group_dns_check, 'and')
def test_null_id_attr(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=None) self.assertEqual('uid', backend._id_attr)
def test_get_user_multiple_results(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) user_info = backend.get_user(username=LDAP_USER_UID) self.assertIsNone(user_info)
def test_authenticate_without_password(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) with self.assertRaises(ValueError): backend.authenticate(LDAP_USER_UID, '')
def test_authenticate(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_PASSWD) self.assertTrue(authenticated)
def test_authenticate_failure_bad_user_password(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated)
def test_scope(self): for scope in ['base', 'onelevel', 'subtree']: backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, scope=scope) self.assertEqual(ldap_backend.SEARCH_SCOPES[scope], backend._scope)
def test_tls_authenticate_validate_cert(self): backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, use_tls=True, cacert=LDAP_CACERT_REAL_PATH, id_attr=LDAP_ID_ATTR) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_PASSWD) self.assertTrue(authenticated)
def test_ssl_authenticate_failure(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, port=LDAPS_PORT, use_ssl=True, id_attr=LDAP_ID_ATTR) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated)
def test_chase_referrals(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR, chase_referrals=False) conn = backend._init_connection() self.assertFalse(conn.get_option(ldap.OPT_REFERRALS)) backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR, chase_referrals=True) conn = backend._init_connection() self.assertTrue(conn.get_option(ldap.OPT_REFERRALS))
def test_get_user(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) user_info = backend.get_user(username=LDAP_USER_UID) self.assertEqual(user_info['cn'], ['Tomaz Muraus']) self.assertEqual(user_info['displayName'], ['Tomaz Muraus']) self.assertEqual(user_info['givenName'], ['Tomaz']) self.assertEqual(user_info['primaryGroupID'], ['513'])
def test_id_attr_and_account_pattern(self): account_pattern = '(|(username={username})(mail={username}))' backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr='user', account_pattern=account_pattern, ) self.assertEqual(account_pattern, backend._account_pattern)
def test_authenticate_or_behavior_success_member_of_single_group_1(self): # User is a memeber of single of possible required groups required_group_dns = ['cn=group1,dc=stackstorm,dc=net'] backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='or') authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertTrue(authenticated)
def test_get_user_groups(self): backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) expected = [ 'cn=testers,dc=stackstorm,dc=net', 'cn=stormers,dc=stackstorm,dc=net' ] groups = backend.get_user_groups(username=LDAP_USER_UID) self.assertEqual(groups, expected)
def test_authenticate(self): ldap_group_dns = ['cn=testers,ou=groups,dc=stackstorm,dc=net'] ldap_user_uid = 'stanley' ldap_user_passwd = 'stanl3y!' backend = ldap_backend.LDAPAuthenticationBackend( self.ldap_bind_dn, self.ldap_bind_pass, self.ldap_base_ou, ldap_group_dns, self.ldap_host, id_attr=self.ldap_id_attr) authenticated = backend.authenticate(ldap_user_uid, ldap_user_passwd) self.assertTrue(authenticated)
def test_authenticate_and_behavior_failure_non_group_member_of_all_required_groups_2( self): # User is member of two of the groups, but none of them are required required_group_dns = [ 'cn=group7,dc=stackstorm,dc=net', 'cn=group8,dc=stackstorm,dc=net' ] backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='and') authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated)
def test_get_user_groups_specifying_group_pattern(self): expected_user_dn = 'unique_userdn_1' expected_username = '******' required_group_dns = [ 'cn=group3,dc=stackstorm,dc=net', 'cn=group4,dc=stackstorm,dc=net' ] scope = 'subtree' scope_number = ldap_backend.SEARCH_SCOPES[scope] group_pattern = ''' (| (& (objectClass=group) (| (memberUserdn={user_dn}) (uniqueMemberUserdn={user_dn}) (memberUid={username}) (uniqueMemberUid={username}) ) ) ) '''.replace('\n', '').replace(' ', '') expected_group_pattern = group_pattern.format( user_dn=expected_user_dn, username=expected_username, ) backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, scope=scope, group_pattern=group_pattern, cache_user_groups_response=False, ) connection = mock.MagicMock() backend._init_connection = mock.MagicMock(return_value=connection) backend._get_user_dn = mock.MagicMock(return_value=expected_user_dn) backend.get_user_groups(expected_username) connection.search_s.assert_called_with(LDAP_BASE_OU, scope_number, expected_group_pattern, [])
def test_client_options(self): client_options = { ldap.OPT_RESTART: 0, ldap.OPT_SIZELIMIT: 2014, ldap.OPT_DIAGNOSTIC_MESSAGE: 'test', # Not using a constant, 20482 is OPT_TIMEOUT '20482': 9 } backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR, client_options=client_options) conn = backend._init_connection() for option_name, option_value in client_options.items(): self.assertEqual(conn.get_option(int(option_name)), option_value)
def test_authenticate_and_is_default_behavior_non_group_member_of_all_required_groups( self): # User is member of two of the required groups and two non-required, but not # all of the required groups # Verify "and" is a default group_dns_check_behavior required_group_dns = [ 'cn=group1,dc=stackstorm,dc=net', 'cn=group2,dc=stackstorm,dc=net', 'cn=group5,dc=stackstorm,dc=net', 'cn=group6,dc=stackstorm,dc=net', ] backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR) authenticated = backend.authenticate(LDAP_USER_UID, LDAP_USER_BAD_PASSWD) self.assertFalse(authenticated)
def test_get_groups_caching_no_cross_username_cache_polution(self): required_group_dns = [ 'cn=group3,dc=stackstorm,dc=net', 'cn=group4,dc=stackstorm,dc=net' ] # Test which verifies that cache items are correctly scoped per username backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, id_attr=LDAP_ID_ATTR, group_dns_check='or', cache_user_groups_response=True) user_groups = backend.get_user_groups(username=LDAP_USER_UID) self.assertEqual(user_groups, ['cn=group3,dc=stackstorm,dc=net']) self.assertEqual(backend._user_groups_cache[LDAP_USER_UID], ['cn=group3,dc=stackstorm,dc=net']) user_groups = backend.get_user_groups(username=LDAP_USER_UID_2) self.assertEqual(user_groups, ['cn=group4,dc=stackstorm,dc=net']) self.assertEqual(backend._user_groups_cache[LDAP_USER_UID_2], ['cn=group4,dc=stackstorm,dc=net'])
def test_special_characters_in_username_are_escaped(self): # User is not member of any of the required group backend = ldap_backend.LDAPAuthenticationBackend(LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, LDAP_GROUP_DNS, LDAP_HOST, id_attr=LDAP_ID_ATTR) values = [ ('stanleyA', 'stanleyA'), ('stanley!@?.,&', 'stanley!@?.,&'), # Special characters () should be escaped ('(stanley)', '\\28stanley\\29'), # Special characters () should be escaped ('(stanley=)', '\\28stanley=\\29'), ] for actual_username, expected_username in values: authenticated = backend.authenticate(actual_username, LDAP_USER_BAD_PASSWD) call_args_1 = ldap.ldapobject.SimpleLDAPObject.search_s.call_args_list[ 0][0] call_args_2 = ldap.ldapobject.SimpleLDAPObject.search_s.call_args_list[ 1][0] # First search_s call (find user by uid) filter_call_value = call_args_1[2] self.assertEqual(filter_call_value, 'uid=%s' % (expected_username)) # Second search_s call (group membership test) filter_call_value = call_args_2[2] self.assertTrue('(memberUid=%s)' % (expected_username) in filter_call_value) ldap.ldapobject.SimpleLDAPObject.search_s = mock.MagicMock( side_effect=[LDAP_USER_SEARCH_RESULT, []])
def test_get_user_specifying_account_pattern(self): expected_username = '******' required_group_dns = [ 'cn=group3,dc=stackstorm,dc=net', 'cn=group4,dc=stackstorm,dc=net' ] scope = 'subtree' scope_number = ldap_backend.SEARCH_SCOPES[scope] account_pattern = ''' (& (objectClass=person) (| (accountName={username}) (mail={username}) ) ) '''.replace('\n', '').replace(' ', '') expected_account_pattern = account_pattern.format( username=expected_username) backend = ldap_backend.LDAPAuthenticationBackend( LDAP_BIND_DN, LDAP_BIND_PASSWORD, LDAP_BASE_OU, required_group_dns, LDAP_HOST, scope=scope, account_pattern=account_pattern, ) connection = mock.MagicMock() backend._init_connection = mock.MagicMock(return_value=connection) backend.get_user(expected_username) connection.search_s.assert_called_once_with(LDAP_BASE_OU, scope_number, expected_account_pattern, [])