Package repoze :: Package who :: Package plugins :: Package ldap :: Module tests
[hide private]

Source Code for Module repoze.who.plugins.ldap.tests

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # repoze.who.plugins.ldap, LDAP authentication for WSGI applications. 
  4  # Copyright (C) 2010 by Gustavo Narea  <http://gustavonarea.net/> and 
  5  #                       Lorenzo M. Catucci <http://www.uniroma2.it/>. 
  6  # Copyright (C) 2008 by Gustavo Narea <http://gustavonarea.net/>.s 
  7  # 
  8  # This file is part of repoze.who.plugins.ldap 
  9  # <http://code.gustavonarea.net/repoze.who.plugins.ldap/> 
 10  # 
 11  # This software is subject to the provisions of the BSD-like license at 
 12  # http://www.repoze.org/LICENSE.txt.  A copy of the license should accompany 
 13  # this distribution.  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL 
 14  # EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, 
 15  # THE IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND 
 16  # FITNESS FOR A PARTICULAR PURPOSE. 
 17  """Test suite for repoze.who.plugins.ldap""" 
 18   
 19  import unittest 
 20   
 21  from dataflake.ldapconnection.tests import fakeldap 
 22  import ldap 
 23  from ldap import modlist, dn 
 24  from ldap.ldapobject import SimpleLDAPObject 
 25  from zope.interface.verify import verifyClass 
 26  from repoze.who.interfaces import IAuthenticator, IMetadataProvider 
 27   
 28  from repoze.who.plugins.ldap import LDAPAuthenticatorPlugin, \ 
 29                                      LDAPAttributesPlugin, \ 
 30                                      LDAPSearchAuthenticatorPlugin 
 31  from repoze.who.plugins.ldap.plugins import make_ldap_connection 
 32   
 33  from base64 import b64encode 
 34   
 35   
36 -class Base(unittest.TestCase):
37 """Base test case for the plugins""" 38
39 - def setUp(self):
40 # Connecting to a fake server with a fake account: 41 conn = fakeldap.FakeLDAPConnection() 42 conn.simple_bind_s('Manager', 'some password') 43 # We must explicitly create the base_dn DIT components 44 fakeldap.addTreeItems(base_dn) 45 # Adding a fake user, which is used in the tests 46 person_attr = {'cn': [fakeuser['cn']], 47 'uid': fakeuser['uid'], 48 'userPassword': [fakeuser['hashedPassword']], 49 'telephone': [fakeuser['telephone']], 50 'mail':[fakeuser['mail']]} 51 conn.add_s(fakeuser['dn'], modlist.addModlist(person_attr)) 52 self.connection = conn 53 # Creating a fake environment: 54 self.env = self._makeEnviron()
55
56 - def tearDown(self):
57 self.connection.delete_s(fakeuser['dn'])
58
59 - def _makeEnviron(self, kw=None):
60 """Create a fake WSGI environment 61 62 This is based on the same method of the test suite of repoze.who. 63 64 """ 65 environ = {} 66 environ['wsgi.version'] = (1,0) 67 if kw is not None: 68 environ.update(kw) 69 return environ
70 71 72 #{ Test cases for the plugins 73 74
75 -class TestMakeLDAPAuthenticatorPlugin(unittest.TestCase):
76 """Tests for the constructor of the L{LDAPAuthenticatorPlugin} plugin""" 77
78 - def test_without_connection(self):
79 self.assertRaises(ValueError, LDAPAuthenticatorPlugin, None, 80 'dc=example,dc=org')
81
82 - def test_without_base_dn(self):
83 conn = fakeldap.FakeLDAPConnection() 84 self.assertRaises(TypeError, LDAPAuthenticatorPlugin, conn) 85 self.assertRaises(ValueError, LDAPAuthenticatorPlugin, conn, None)
86
87 - def test_with_connection(self):
88 conn = fakeldap.FakeLDAPConnection() 89 LDAPAuthenticatorPlugin(conn, 'dc=example,dc=org')
90
91 - def test_connection_is_url(self):
92 LDAPAuthenticatorPlugin('ldap://example.org', 'dc=example,dc=org')
93 94
95 -class TestLDAPAuthenticatorPlugin(Base):
96 """Tests for the L{LDAPAuthenticatorPlugin} IAuthenticator plugin""" 97
98 - def setUp(self):
99 super(TestLDAPAuthenticatorPlugin, self).setUp() 100 # Loading the plugin: 101 self.plugin = LDAPAuthenticatorPlugin(self.connection, base_dn)
102
103 - def test_implements(self):
104 verifyClass(IAuthenticator, LDAPAuthenticatorPlugin, tentative=True)
105
107 result = self.plugin.authenticate(self.env, None) 108 self.assertEqual(result, None)
109
111 identity1 = {'login': fakeuser['uid']} 112 identity2 = {'password': fakeuser['password']} 113 result1 = self.plugin.authenticate(self.env, identity1) 114 result2 = self.plugin.authenticate(self.env, identity2) 115 self.assertEqual(result1, None) 116 self.assertEqual(result2, None)
117
119 identity = {'login': 'i_dont_exist', 120 'password': 'super secure password'} 121 result = self.plugin.authenticate(self.env, identity) 122 self.assertEqual(result, None)
123
125 identity = {'login': fakeuser['uid'], 126 'password': 'wrong password'} 127 result = self.plugin.authenticate(self.env, identity) 128 self.assertEqual(result, None)
129
131 identity = {'login': fakeuser['uid'], 132 'password': fakeuser['password']} 133 result = self.plugin.authenticate(self.env, identity) 134 self.assertEqual(result, fakeuser['dn'])
135
137 """L{LDAPAuthenticatorPlugin._get_dn} should be overriden with no 138 problems""" 139 plugin = CustomLDAPAuthenticatorPlugin(self.connection, base_dn) 140 identity = {'login': fakeuser['uid'], 141 'password': fakeuser['password']} 142 result = plugin.authenticate(self.env, identity) 143 expected = 'uid=%s,%s' % (fakeuser['uid'], base_dn) 144 self.assertEqual(result, expected) 145 self.assertTrue(plugin.called)
146
147 -class TestLDAPSearchAuthenticatorPluginNaming(Base):
148 """Tests for the L{LDAPSearchAuthenticatorPlugin} IAuthenticator plugin""" 149
150 - def setUp(self):
151 super(TestLDAPSearchAuthenticatorPluginNaming, self).setUp() 152 # Loading the plugin: 153 self.plugin = LDAPSearchAuthenticatorPlugin( 154 self.connection, 155 base_dn, 156 naming_attribute='telephone', 157 )
158
160 identity = {'login': 'i_dont_exist', 161 'password': 'super secure password'} 162 result = self.plugin.authenticate(self.env, identity) 163 self.assertEqual(result, None)
164
166 identity = {'login': fakeuser['telephone'], 167 'password': 'wrong password'} 168 result = self.plugin.authenticate(self.env, identity) 169 self.assertEqual(result, None)
170
172 identity = {'login': fakeuser['telephone'], 173 'password': fakeuser['password']} 174 result = self.plugin.authenticate(self.env, identity) 175 self.assertEqual(result, fakeuser['dn'])
176
177 -class TestLDAPAuthenticatorReturnLogin(Base):
178 """ 179 Tests the L{LDAPAuthenticatorPlugin} IAuthenticator plugin returning 180 login. 181 182 """ 183
184 - def setUp(self):
185 super(TestLDAPAuthenticatorReturnLogin, self).setUp() 186 # Loading the plugin: 187 self.plugin = LDAPAuthenticatorPlugin( 188 self.connection, 189 base_dn, 190 returned_id='login', 191 )
192
194 identity = {'login': 'i_dont_exist', 195 'password': 'super secure password'} 196 result = self.plugin.authenticate(self.env, identity) 197 self.assertEqual(result, None)
198
200 identity = {'login': fakeuser['uid'], 201 'password': 'wrong password'} 202 result = self.plugin.authenticate(self.env, identity) 203 self.assertEqual(result, None)
204
206 identity = {'login': fakeuser['uid'], 207 'password': fakeuser['password']} 208 result = self.plugin.authenticate(self.env, identity) 209 self.assertEqual(result, fakeuser['uid'])
210
212 identity = {'login': fakeuser['uid'], 213 'password': fakeuser['password']} 214 expected_dn = '<dn:%s>' % b64encode(fakeuser['dn']) 215 result = self.plugin.authenticate(self.env, identity) 216 self.assertEqual(identity['userdata'], expected_dn)
217 218
219 -class TestLDAPSearchAuthenticatorReturnLogin(Base):
220 """ 221 Tests the L{LDAPSearchAuthenticatorPlugin} IAuthenticator plugin returning 222 login. 223 224 """ 225
226 - def setUp(self):
227 super(TestLDAPSearchAuthenticatorReturnLogin, self).setUp() 228 # Loading the plugin: 229 self.plugin = LDAPSearchAuthenticatorPlugin( 230 self.connection, 231 base_dn, 232 returned_id='login', 233 )
234
236 identity = {'login': 'i_dont_exist', 237 'password': 'super secure password'} 238 result = self.plugin.authenticate(self.env, identity) 239 self.assertEqual(result, None)
240
242 identity = {'login': fakeuser['uid'], 243 'password': 'wrong password'} 244 result = self.plugin.authenticate(self.env, identity) 245 self.assertEqual(result, None)
246
248 identity = {'login': fakeuser['uid'], 249 'password': fakeuser['password']} 250 result = self.plugin.authenticate(self.env, identity) 251 self.assertEqual(result, fakeuser['uid'])
252
254 identity = {'login': fakeuser['uid'], 255 'password': fakeuser['password']} 256 expected_dn = '<dn:%s>' % b64encode(fakeuser['dn']) 257 result = self.plugin.authenticate(self.env, identity) 258 self.assertEqual(identity['userdata'], expected_dn)
259 260
261 -class TestLDAPAuthenticatorPluginStartTls(Base):
262 """Tests for the L{LDAPAuthenticatorPlugin} IAuthenticator plugin""" 263
264 - def setUp(self):
265 super(TestLDAPAuthenticatorPluginStartTls, self).setUp() 266 # Loading the plugin: 267 self.plugin = LDAPAuthenticatorPlugin(self.connection, base_dn, 268 start_tls=True)
269
270 - def test_implements(self):
271 verifyClass(IAuthenticator, LDAPAuthenticatorPlugin, tentative=True)
272 273
274 -class TestMakeLDAPAttributesPlugin(unittest.TestCase):
275 """Tests for the constructor of L{LDAPAttributesPlugin}""" 276
278 self.assertRaises(ValueError, LDAPAttributesPlugin, None, 'cn')
279
280 - def test_attributes_is_none(self):
281 """If attributes is None then fetch all the attributes""" 282 plugin = LDAPAttributesPlugin('ldap://localhost', None) 283 self.assertEqual(plugin.attributes, None)
284
286 attributes = "cn,uid,mail" 287 plugin = LDAPAttributesPlugin('ldap://localhost', attributes) 288 self.assertEqual(plugin.attributes, attributes.split(','))
289
291 attributes = "mail" 292 plugin = LDAPAttributesPlugin('ldap://localhost', attributes) 293 self.assertEqual(plugin.attributes, ['mail'])
294
296 # The plugin, with a tuple as attributes 297 attributes_t = ('cn', 'mail') 298 plugin_t = LDAPAttributesPlugin('ldap://localhost', attributes_t) 299 self.assertEqual(plugin_t.attributes, list(attributes_t)) 300 # The plugin, with a list as attributes 301 attributes_l = ['cn', 'mail'] 302 plugin_l = LDAPAttributesPlugin('ldap://localhost', attributes_l) 303 self.assertEqual(plugin_l.attributes, attributes_l) 304 # The plugin, with a dict as attributes 305 attributes_d = {'first': 'cn', 'second': 'mail'} 306 plugin_d = LDAPAttributesPlugin('ldap://localhost', attributes_d) 307 self.assertEqual(plugin_d.attributes, list(attributes_d))
308
310 self.assertRaises(ValueError, LDAPAttributesPlugin, 'ldap://localhost', 311 12345)
312
314 LDAPAttributesPlugin('ldap://localhost', 'cn', '(objectClass=*)')
315 316
317 -class TestLDAPAttributesPlugin(Base):
318 """Tests for the L{LDAPAttributesPlugin} IMetadata plugin""" 319
320 - def test_implements(self):
321 verifyClass(IMetadataProvider, LDAPAttributesPlugin, tentative=True)
322
323 - def test_add_metadata(self):
324 plugin = LDAPAttributesPlugin(self.connection) 325 environ = {} 326 identity = {'repoze.who.userid': fakeuser['dn']} 327 expected_identity = { 328 'repoze.who.userid': fakeuser['dn'], 329 'cn': [fakeuser['cn']], 330 'userPassword': [fakeuser['hashedPassword']], 331 'uid': fakeuser['uid'], 332 'telephone': [ fakeuser['telephone']], 333 'mail': [fakeuser['mail']] 334 } 335 plugin.add_metadata(environ, identity) 336 self.assertEqual(identity, expected_identity)
337 338 339 # Test cases for plugin utilities 340
341 -class TestLDAPConnectionFactory(unittest.TestCase):
342 """Tests for L{make_ldap_connection}""" 343
345 conn = fakeldap.FakeLDAPConnection() 346 self.assertEqual(make_ldap_connection(conn), conn)
347
348 - def test_connection_is_str(self):
349 conn = make_ldap_connection('ldap://example.org') 350 self.assertTrue(isinstance(conn, SimpleLDAPObject))
351
353 conn = make_ldap_connection(u'ldap://example.org') 354 self.assertTrue(isinstance(conn, SimpleLDAPObject))
355
356 - def test_connection_is_none(self):
357 self.assertRaises(ValueError, make_ldap_connection, None)
358 359 360 # Test cases for the fakeldap connection itself 361
362 -class TestLDAPConnection(unittest.TestCase):
363 """Connection use tests""" 364
365 - def setUp(self):
366 # Connecting to a fake server with a fake account: 367 conn = fakeldap.FakeLDAPConnection() 368 conn.simple_bind_s('Manager', 'some password') 369 # We must explicitly create the base_dn DIT components 370 fakeldap.addTreeItems(base_dn) 371 # Adding a fake user, which is used in the tests 372 self.person_attr = {'cn': [fakeuser['cn']], 373 'uid': fakeuser['uid'], 374 'userPassword': [fakeuser['hashedPassword']], 375 'telephone':[fakeuser['telephone']], 376 'objectClass': ['top']} 377 conn.add_s(fakeuser['dn'], modlist.addModlist(self.person_attr)) 378 self.connection = conn
379
380 - def tearDown(self):
381 self.connection.delete_s(fakeuser['dn'])
382
384 rs = self.connection.search_s( 385 base_dn, 386 ldap.SCOPE_SUBTREE, 387 '(uid=%s)' % fakeuser['uid'], 388 ) 389 self.assertEqual(rs[0][0], fakeuser['dn']) 390 self.assertEqual(rs[0][1], self.person_attr )
391
393 rs = self.connection.search_s( 394 base_dn, 395 ldap.SCOPE_SUBTREE, 396 '(&(objectclass=*)(uid=%s))' % fakeuser['uid'], 397 ) 398 self.assertEqual(rs[0][0], fakeuser['dn']) 399 self.assertEqual(rs[0][1], self.person_attr )
400
402 rs = self.connection.search_s( 403 base_dn, 404 ldap.SCOPE_SUBTREE, 405 'uid=%s' % fakeuser['uid'], 406 ) 407 self.assertEqual(rs[0][0], fakeuser['dn']) 408 self.assertEqual(rs[0][1], self.person_attr )
409
411 rs = self.connection.search_s( 412 base_dn, 413 ldap.SCOPE_SUBTREE, 414 '(mail=%s)' % fakeuser['mail'], 415 ) 416 self.assertEqual(rs[0][0], fakeuser['dn']) 417 self.assertEqual(rs[0][1], self.person_attr )
418
420 rs = self.connection.search_s( 421 base_dn, 422 ldap.SCOPE_SUBTREE, 423 '(telephone=+%s)' % fakeuser['telephone'], 424 ) 425 self.assertEqual(rs[0][0], fakeuser['dn']) 426 self.assertEqual(rs[0][1], self.person_attr )
427 428 #{ Fixtures 429 430 base_dn = 'ou=people,dc=example,dc=org' 431 432 fakeuser = { 433 'dn': 'uid=carla,%s' % base_dn, 434 'uid': 'carla', 435 'cn': 'Carla Paola', 436 'mail': 'carla@example.org', 437 'telephone': '39 123 456 789', 438 'password': 'hello', 439 'hashedPassword': '{SHA}qvTGHdzF6KLavt4PO0gs2a6pQ00=' 440 } 441 442
443 -class CustomLDAPAuthenticatorPlugin(LDAPAuthenticatorPlugin):
444 """Fake class to test that L{LDAPAuthenticatorPlugin._get_dn} can be 445 overriden with no problems""" 446
447 - def _get_dn(self, environ, identity):
448 self.called = True 449 try: 450 return u'uid=%s,%s' % (identity['login'], self.base_dn) 451 except (KeyError, TypeError): 452 raise ValueError, ('Could not find the DN from the identity and ' 453 'environment')
454 455 456 #} 457 458
459 -def suite():
460 """ 461 Return the test suite. 462 463 @return: The test suite for the plugin. 464 @rtype: C{unittest.TestSuite} 465 466 """ 467 suite = unittest.TestSuite() 468 suite.addTest(unittest.makeSuite(TestLDAPConnection, "test")) 469 suite.addTest(unittest.makeSuite(TestMakeLDAPAuthenticatorPlugin, "test")) 470 suite.addTest(unittest.makeSuite(TestLDAPAuthenticatorPlugin, "test")) 471 suite.addTest(unittest.makeSuite(TestMakeLDAPAttributesPlugin, "test")) 472 suite.addTest(unittest.makeSuite(TestLDAPAttributesPlugin, "test")) 473 suite.addTest(unittest.makeSuite(TestLDAPConnectionFactory, "test")) 474 suite.addTest(unittest.makeSuite(TestLDAPSearchAuthenticatorPluginNaming, 475 "test")) 476 suite.addTest(unittest.makeSuite(TestLDAPAuthenticatorReturnLogin, "test")) 477 suite.addTest(unittest.makeSuite(TestLDAPSearchAuthenticatorReturnLogin, 478 "test")) 479 suite.addTest(unittest.makeSuite(TestLDAPAuthenticatorPluginStartTls, 480 "test")) 481 return suite
482 483 484 if __name__ == '__main__': 485 unittest.main(defaultTest='suite') 486