1111
1212from django .apps import apps
1313from django .conf import settings
14+ from django .contrib .auth import authenticate
1415from django .contrib .auth import get_user_model
1516from django .contrib .auth .models import Group
1617from django .contrib .auth .models import Permission
2122from django .urls import reverse
2223
2324import ldap
25+ import slapdtest
2426from django_auth_ldap .backend import _LDAPUserGroups
2527from django_auth_ldap .config import GroupOfNamesType
2628from django_auth_ldap .config import LDAPSearch
2729from guardian .shortcuts import assign_perm
28- from mockldap import MockLdap
30+ from ldap . ldapobject import SimpleLDAPObject
2931
3032from dje .ldap_backend import DejaCodeLDAPBackend
3133from dje .models import Dataspace
3840Product = apps .get_model ("product_portfolio" , "Product" )
3941
4042
41- AUTH_LDAP_USER_ATTR_MAP = {
42- "first_name" : "givenName" ,
43- "last_name" : "sn" ,
44- "email" : "mail" ,
45- }
46-
47-
48- LDAP_GROUP_SETTINGS = {
49- "AUTH_LDAP_GROUP_SEARCH" : LDAPSearch (
50- "ou=groups,dc=nexb,dc=com" , ldap .SCOPE_SUBTREE , "(objectClass=groupOfNames)"
51- ),
52- "AUTH_LDAP_GROUP_TYPE" : GroupOfNamesType (),
53- }
43+ LDIF = """
44+ dn: o=test
45+ objectClass: organization
46+ o: test
47+
48+ dn: ou=people,o=test
49+ objectClass: organizationalUnit
50+ ou: people
51+
52+ dn: ou=groups,o=test
53+ objectClass: organizationalUnit
54+ ou: groups
55+
56+ dn: uid=bob,ou=people,o=test
57+ objectClass: person
58+ objectClass: organizationalPerson
59+ objectClass: inetOrgPerson
60+ objectClass: posixAccount
61+ cn: bob
62+ uid: bob
63+ userPassword: secret
64+ uidNumber: 1001
65+ gidNumber: 50
66+ givenName: Robert
67+ sn: Smith
68+ homeDirectory: /home/bob
69+ 70+
71+ dn: cn=active,ou=groups,o=test
72+ cn: active
73+ objectClass: groupOfNames
74+ member: uid=bob,ou=people,o=test
75+ """
5476
5577
5678@override_settings (
57- AUTH_LDAP_SERVER_URI = "ldap://localhost/" ,
5879 AUTHENTICATION_BACKENDS = ("dje.ldap_backend.DejaCodeLDAPBackend" ,),
5980 AUTH_LDAP_DATASPACE = "nexB" ,
60- AUTH_LDAP_USER_SEARCH = LDAPSearch (
61- "ou=people,dc=nexb,dc=com" , ldap .SCOPE_SUBTREE , "(samaccountname=%(user)s)"
81+ AUTH_LDAP_START_TLS = False ,
82+ AUTH_LDAP_USER_DN_TEMPLATE = "uid=%(user)s,ou=people,o=test" ,
83+ AUTH_LDAP_USER_SEARCH = LDAPSearch ("ou=people,o=test" , ldap .SCOPE_SUBTREE , "(uid=%(user)s)" ),
84+ AUTH_LDAP_UBIND_AS_AUTHENTICATING_USER = True ,
85+ AUTH_LDAP_USER_ATTR_MAP = {
86+ "first_name" : "givenName" ,
87+ "last_name" : "sn" ,
88+ "email" : "mail" ,
89+ },
90+ AUTH_LDAP_GROUP_SEARCH = LDAPSearch (
91+ "ou=groups,o=test" , ldap .SCOPE_SUBTREE , "(objectClass=groupOfNames)"
6292 ),
63- ** LDAP_GROUP_SETTINGS ,
93+ AUTH_LDAP_GROUP_TYPE = GroupOfNamesType () ,
6494)
6595class DejaCodeLDAPBackendTestCase (TestCase ):
66- top = ("dc=com" , {"dc" : "com" })
67- nexb = ("dc=nexb,dc=com" , {"dc" : "nexb" })
68- people = ("ou=people,dc=nexb,dc=com" , {"ou" : "people" })
69- groups = ("ou=groups,dc=nexb,dc=com" , {"ou" : "groups" })
70-
71- bob = (
72- "cn=bob,ou=people,dc=nexb,dc=com" ,
73- {
74- "cn" : "bob" ,
75- "samaccountname" : "bob" ,
76- "uid" : ["bob" ],
77- "userPassword" : ["secret" ],
78- 79- "givenName" : ["Robert" ],
80- "sn" : ["Smith" ],
81- },
82- )
83-
84- group_active = (
85- "cn=active,ou=groups,dc=nexb,dc=com" ,
86- {
87- "cn" : ["active" ],
88- "objectClass" : ["groupOfNames" ],
89- "member" : ["cn=bob,ou=people,dc=nexb,dc=com" ],
90- },
91- )
92-
93- group_not_in_database = (
94- "cn=not_in_database,ou=groups,dc=nexb,dc=com" ,
95- {
96- "cn" : ["not_in_database" ],
97- "objectClass" : ["groupOfNames" ],
98- "member" : ["cn=bob,ou=people,dc=nexb,dc=com" ],
99- },
100- )
101-
102- group_superuser = (
103- "cn=superuser,ou=groups,dc=nexb,dc=com" ,
104- {
105- "cn" : ["superuser" ],
106- "objectClass" : ["groupOfNames" ],
107- "member" : ["cn=bob,ou=people,dc=nexb,dc=com" ],
108- },
109- )
110-
111- # This is the content of our mock LDAP directory. It takes the form
112- # {dn: {attr: [value, ...], ...}, ...}.
113- directory = dict (
114- [
115- top ,
116- nexb ,
117- people ,
118- groups ,
119- bob ,
120- group_active ,
121- group_not_in_database ,
122- group_superuser ,
123- ]
124- )
96+ server_class = slapdtest .SlapdObject
97+ ldap_object_class = SimpleLDAPObject
12598
12699 @classmethod
127100 def setUpClass (cls ):
128101 super ().setUpClass ()
129102 cls .configure_logger ()
130- # We only need to create the MockLdap instance once. The content we
131- # pass in will be used for all LDAP connections.
132- cls .mockldap = MockLdap (cls .directory )
103+
104+ cls .server = cls .server_class ()
105+ cls .server .suffix = "o=test"
106+ cls .server .openldap_schema_files = [
107+ "core.ldif" ,
108+ "cosine.ldif" ,
109+ "inetorgperson.ldif" ,
110+ "nis.ldif" ,
111+ ]
112+ cls .server .start ()
113+ cls .server .ldapadd (LDIF )
114+
115+ # Override the AUTH_LDAP_SERVER_URI with the dynamic URI
116+ cls ._settings_override = override_settings (AUTH_LDAP_SERVER_URI = cls .server .ldap_uri )
117+ cls ._settings_override .enable ()
133118
134119 @classmethod
135120 def tearDownClass (cls ):
136121 super ().tearDownClass ()
137- del cls .mockldap
122+ cls .server .stop ()
123+ # Disable the settings override
124+ cls ._settings_override .disable ()
138125
139126 @classmethod
140127 def configure_logger (cls ):
@@ -145,24 +132,46 @@ def configure_logger(cls):
145132 def setUp (self ):
146133 cache .clear ()
147134
148- # Patch ldap.initialize
149- self .mockldap .start ()
150- self .ldapobj = self .mockldap ["ldap://localhost/" ]
151-
152- # DejaCode objects
153135 self .nexb_dataspace = Dataspace .objects .create (name = "nexB" )
154136 self .dejacode_group_active = Group .objects .create (name = "active" )
155137 self .dejacode_group1 = Group .objects .create (name = "group1" )
156-
157138 change_license_perm = Permission .objects .get_by_natural_key (
158139 "change_license" , "license_library" , "license"
159140 )
160141 self .dejacode_group_active .permissions .add (change_license_perm )
161142
162- def tearDown (self ):
163- # Stop patching ldap.initialize and reset state.
164- self .mockldap .stop ()
165- del self .ldapobj
143+ def test_ldap_authentication_populate_user (self ):
144+ user = authenticate (username = "bob" , password = "secret" )
145+ self .assertEqual (user .username , "bob" )
146+ self .assertEqual (user .first_name , "Robert" )
147+ self .assertEqual (user .last_name , "Smith" )
148+ self .
assertEqual (
user .
email ,
"[email protected] " )
149+
150+ def test_bind_and_search (self ):
151+ # Connect to the temporary slapd server
152+ conn = self .ldap_object_class (self .server .ldap_uri )
153+ conn .simple_bind_s (self .server .root_dn , self .server .root_pw )
154+
155+ # Search for the top entry
156+ result = conn .search_s (self .server .suffix , ldap .SCOPE_BASE )
157+ self .assertEqual (len (result ), 1 )
158+ dn , entry = result [0 ]
159+ self .assertEqual (dn , self .server .suffix )
160+
161+ def test_ldap_group_active_properly_setup_and_searchable (self ):
162+ conn = self .ldap_object_class (self .server .ldap_uri )
163+ results = conn .search_s ("ou=groups,o=test" , ldap .SCOPE_ONELEVEL , "(cn=active)" )
164+ expected = [
165+ (
166+ "cn=active,ou=groups,o=test" ,
167+ {
168+ "cn" : [b"active" ],
169+ "objectClass" : [b"groupOfNames" ],
170+ "member" : [b"uid=bob,ou=people,o=test" ],
171+ },
172+ )
173+ ]
174+ self .assertEqual (expected , results )
166175
167176 @override_settings (AUTH_LDAP_AUTOCREATE_USER = False )
168177 def test_ldap_authentication_no_autocreate_user (self ):
@@ -208,7 +217,7 @@ def test_ldap_authentication_autocreate_user_proper_dataspace(self):
208217 # Next login, the DB user is re-used
209218 self .assertTrue (self .client .login (username = "bob" , password = "secret" ))
210219
211- @override_settings (AUTH_LDAP_USER_ATTR_MAP = AUTH_LDAP_USER_ATTR_MAP )
220+ # @override_settings(AUTH_LDAP_USER_ATTR_MAP=AUTH_LDAP_USER_ATTR_MAP)
212221 def test_ldap_authentication_autocreate_user_with_attr_map (self ):
213222 self .assertFalse (DejacodeUser .objects .filter (username = "bob" ).exists ())
214223
@@ -221,7 +230,7 @@ def test_ldap_authentication_autocreate_user_with_attr_map(self):
221230 self .assertEqual (self .nexb_dataspace , created_user .dataspace )
222231
223232 @override_settings (
224- AUTH_LDAP_USER_ATTR_MAP = AUTH_LDAP_USER_ATTR_MAP ,
233+ # AUTH_LDAP_USER_ATTR_MAP=AUTH_LDAP_USER_ATTR_MAP,
225234 AUTH_LDAP_ALWAYS_UPDATE_USER = True ,
226235 )
227236 def test_ldap_authentication_update_user_with_attr_map (self ):
@@ -243,22 +252,6 @@ def test_ldap_authentication_update_user_with_attr_map(self):
243252 self .
assertEqual (
"[email protected] " ,
user .
email )
244253 self .assertEqual (self .nexb_dataspace , user .dataspace )
245254
246- def test_ldap_group_active_properly_setup_and_searchable (self ):
247- conn = ldap .initialize ("ldap://localhost/" )
248- results = conn .search_s ("ou=groups,dc=nexb,dc=com" , ldap .SCOPE_ONELEVEL , "(cn=active)" )
249-
250- expected = [
251- (
252- "cn=active,ou=groups,dc=nexb,dc=com" ,
253- {
254- "cn" : ["active" ],
255- "objectClass" : ["groupOfNames" ],
256- "member" : ["cn=bob,ou=people,dc=nexb,dc=com" ],
257- },
258- )
259- ]
260- self .assertEqual (expected , results )
261-
262255 @override_settings (AUTH_LDAP_FIND_GROUP_PERMS = True )
263256 def test_ldap_authentication_group_permissions (self ):
264257 bob = create_user (
"bob" ,
self .
nexb_dataspace ,
email = "[email protected] " ,
is_staff = True )
@@ -390,3 +383,65 @@ def test_ldap_object_secured_access(self):
390383 # The `ObjectPermissionBackend` is not needed since `ProductSecuredManager.get_queryset()`
391384 # calls directly `guardian.shortcuts.get_objects_for_user`
392385 self .assertEqual (200 , self .client .get (url ).status_code )
386+
387+
388+ # class DejaCodeLDAPBackendTestCase(TestCase):
389+ # top = ("dc=com", {"dc": "com"})
390+ # nexb = ("dc=nexb,dc=com", {"dc": "nexb"})
391+ # people = ("ou=people,dc=nexb,dc=com", {"ou": "people"})
392+ # groups = ("ou=groups,dc=nexb,dc=com", {"ou": "groups"})
393+ #
394+ # bob = (
395+ # "cn=bob,ou=people,dc=nexb,dc=com",
396+ # {
397+ # "cn": "bob",
398+ # "samaccountname": "bob",
399+ # "uid": ["bob"],
400+ # "userPassword": ["secret"],
401+ 402+ # "givenName": ["Robert"],
403+ # "sn": ["Smith"],
404+ # },
405+ # )
406+ #
407+ # group_active = (
408+ # "cn=active,ou=groups,dc=nexb,dc=com",
409+ # {
410+ # "cn": ["active"],
411+ # "objectClass": ["groupOfNames"],
412+ # "member": ["cn=bob,ou=people,dc=nexb,dc=com"],
413+ # },
414+ # )
415+ #
416+ # group_not_in_database = (
417+ # "cn=not_in_database,ou=groups,dc=nexb,dc=com",
418+ # {
419+ # "cn": ["not_in_database"],
420+ # "objectClass": ["groupOfNames"],
421+ # "member": ["cn=bob,ou=people,dc=nexb,dc=com"],
422+ # },
423+ # )
424+ #
425+ # group_superuser = (
426+ # "cn=superuser,ou=groups,dc=nexb,dc=com",
427+ # {
428+ # "cn": ["superuser"],
429+ # "objectClass": ["groupOfNames"],
430+ # "member": ["cn=bob,ou=people,dc=nexb,dc=com"],
431+ # },
432+ # )
433+ #
434+ # # This is the content of our mock LDAP directory. It takes the form
435+ # # {dn: {attr: [value, ...], ...}, ...}.
436+ # directory = dict(
437+ # [
438+ # top,
439+ # nexb,
440+ # people,
441+ # groups,
442+ # bob,
443+ # group_active,
444+ # group_not_in_database,
445+ # group_superuser,
446+ # ]
447+ # )
0 commit comments