1 |
1 |
# -*- coding: utf-8 -*-
|
|
2 |
#
|
|
3 |
# Copyright (C) 2017-2019 Entr'ouvert
|
|
4 |
#
|
|
5 |
# This program is free software: you can redistribute it and/or modify it
|
|
6 |
# under the terms of the GNU Affero General Public License as published
|
|
7 |
# by the Free Software Foundation, either version 3 of the License, or
|
|
8 |
# (at your option) any later version.
|
|
9 |
#
|
|
10 |
# This program is distributed in the hope that it will be useful,
|
|
11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
# GNU Affero General Public License for more details.
|
|
14 |
#
|
|
15 |
# You should have received a copy of the GNU Affero General Public License
|
|
16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17 |
|
2 |
18 |
import os
|
3 |
19 |
|
4 |
20 |
import pytest
|
... | ... | |
6 |
22 |
|
7 |
23 |
import ldap
|
8 |
24 |
from ldap.dn import escape_dn_chars
|
9 |
|
import ldap
|
10 |
25 |
|
11 |
26 |
from ldaptools.slapd import Slapd, has_slapd
|
12 |
27 |
from django.contrib.auth import get_user_model
|
... | ... | |
18 |
33 |
from authentic2.a2_rbac.utils import get_default_ou
|
19 |
34 |
from django_rbac.utils import get_ou_model
|
20 |
35 |
from authentic2.backends import ldap_backend
|
21 |
|
from authentic2 import crypto
|
|
36 |
from authentic2 import crypto, models
|
22 |
37 |
|
23 |
38 |
import utils
|
24 |
39 |
|
|
40 |
User = get_user_model()
|
|
41 |
|
25 |
42 |
pytestmark = pytest.mark.skipunless(has_slapd(), reason='slapd is not installed')
|
26 |
43 |
|
27 |
44 |
USERNAME = u'etienne.michu'
|
... | ... | |
62 |
79 |
cn: Étienne Michu
|
63 |
80 |
sn: Michu
|
64 |
81 |
gn: Étienne
|
|
82 |
l: Paris
|
65 |
83 |
mail: etienne.michu@example.net
|
66 |
84 |
|
67 |
85 |
dn: cn=group1,o=ôrga
|
... | ... | |
77 |
95 |
cn: Étienne Michu
|
78 |
96 |
sn: Michu
|
79 |
97 |
gn: Étienne
|
|
98 |
l: locality{i}
|
80 |
99 |
mail: etienne.michu@example.net
|
81 |
100 |
|
82 |
101 |
'''.format(i=i, password=PASS))
|
... | ... | |
97 |
116 |
conn.simple_bind_s(DN, PASS)
|
98 |
117 |
|
99 |
118 |
|
100 |
|
@pytest.mark.django_db
|
101 |
|
def test_simple(slapd, settings, client):
|
|
119 |
def test_simple(slapd, settings, client, db):
|
102 |
120 |
settings.LDAP_AUTH_SETTINGS = [{
|
103 |
121 |
'url': [slapd.ldap_url],
|
104 |
122 |
'basedn': u'o=ôrga',
|
... | ... | |
109 |
127 |
'password': PASS}, follow=True)
|
110 |
128 |
assert result.status_code == 200
|
111 |
129 |
assert 'Étienne Michu' in str(result)
|
112 |
|
User = get_user_model()
|
113 |
130 |
assert User.objects.count() == 1
|
114 |
131 |
user = User.objects.get()
|
115 |
132 |
assert user.username == u'%s@ldap' % USERNAME
|
... | ... | |
138 |
155 |
'password': PASS}, follow=True)
|
139 |
156 |
assert result.status_code == 200
|
140 |
157 |
assert 'Étienne Michu' in str(result)
|
141 |
|
User = get_user_model()
|
142 |
158 |
assert User.objects.count() == 1
|
143 |
159 |
user = User.objects.get()
|
144 |
160 |
assert user.username == u'%s@ldap' % USERNAME
|
... | ... | |
152 |
168 |
assert not user.check_password(PASS)
|
153 |
169 |
assert 'password' not in client.session['ldap-data']
|
154 |
170 |
|
155 |
|
@pytest.mark.django_db
|
156 |
|
def test_double_login(slapd, simple_user, settings, app):
|
|
171 |
|
|
172 |
def test_double_login(slapd, simple_user, settings, app, db):
|
157 |
173 |
settings.LDAP_AUTH_SETTINGS = [{
|
158 |
174 |
'url': [slapd.ldap_url],
|
159 |
175 |
'basedn': u'o=ôrga',
|
... | ... | |
165 |
181 |
utils.login(app, UID, password=PASS, path='/admin/')
|
166 |
182 |
|
167 |
183 |
|
168 |
|
@pytest.mark.django_db
|
169 |
|
def test_keep_password_in_session(slapd, settings, client):
|
|
184 |
def test_keep_password_in_session(slapd, settings, client, db):
|
170 |
185 |
settings.LDAP_AUTH_SETTINGS = [{
|
171 |
186 |
'url': [slapd.ldap_url],
|
172 |
187 |
'basedn': u'o=ôrga',
|
... | ... | |
178 |
193 |
'password': PASS.decode('utf-8')}, follow=True)
|
179 |
194 |
assert result.status_code == 200
|
180 |
195 |
assert 'Étienne Michu' in str(result)
|
181 |
|
User = get_user_model()
|
182 |
196 |
assert User.objects.count() == 1
|
183 |
197 |
user = User.objects.get()
|
184 |
198 |
assert user.username == u'%s@ldap' % USERNAME
|
... | ... | |
207 |
221 |
'password': PASS}, follow=True)
|
208 |
222 |
assert result.status_code == 200
|
209 |
223 |
assert 'Étienne Michu' in str(result)
|
210 |
|
User = get_user_model()
|
211 |
224 |
assert User.objects.count() == 1
|
212 |
225 |
user = User.objects.get()
|
213 |
226 |
assert user.username == u'%s@ldap' % USERNAME
|
... | ... | |
217 |
230 |
assert not user.check_password(PASS)
|
218 |
231 |
|
219 |
232 |
|
220 |
|
@pytest.mark.django_db
|
221 |
|
def test_wrong_ou(slapd, settings, client):
|
|
233 |
def test_wrong_ou(slapd, settings, client, db):
|
222 |
234 |
settings.LDAP_AUTH_SETTINGS = [{
|
223 |
235 |
'url': [slapd.ldap_url],
|
224 |
236 |
'basedn': u'o=ôrga',
|
... | ... | |
246 |
258 |
assert formatter.format('uid={uid}', uid=['john doé!#$"\'-_']) == 'uid=john doé!#$\\"\'-_'
|
247 |
259 |
|
248 |
260 |
|
249 |
|
@pytest.mark.django_db
|
250 |
|
def test_group_mapping(slapd, settings, client):
|
|
261 |
def test_group_mapping(slapd, settings, client, db):
|
251 |
262 |
from django.contrib.auth.models import Group
|
252 |
263 |
|
253 |
264 |
settings.LDAP_AUTH_SETTINGS = [{
|
... | ... | |
268 |
279 |
assert response.context['user'].groups.count() == 1
|
269 |
280 |
|
270 |
281 |
|
271 |
|
@pytest.mark.django_db
|
272 |
|
def test_posix_group_mapping(slapd, settings, client):
|
|
282 |
def test_posix_group_mapping(slapd, settings, client, db):
|
273 |
283 |
from django.contrib.auth.models import Group
|
274 |
284 |
|
275 |
285 |
settings.LDAP_AUTH_SETTINGS = [{
|
... | ... | |
291 |
301 |
assert response.context['user'].groups.count() == 1
|
292 |
302 |
|
293 |
303 |
|
294 |
|
@pytest.mark.django_db
|
295 |
|
def test_group_to_role_mapping(slapd, settings, client):
|
|
304 |
def test_group_to_role_mapping(slapd, settings, client, db):
|
296 |
305 |
from authentic2.a2_rbac.models import Role
|
297 |
306 |
|
298 |
307 |
Role.objects.get_or_create(name='Role1')
|
... | ... | |
311 |
320 |
assert response.context['user'].roles.count() == 1
|
312 |
321 |
|
313 |
322 |
|
314 |
|
@pytest.mark.django_db
|
315 |
|
def test_posix_group_to_role_mapping(slapd, settings, client):
|
|
323 |
def test_posix_group_to_role_mapping(slapd, settings, client, db):
|
316 |
324 |
from authentic2.a2_rbac.models import Role
|
317 |
325 |
|
318 |
326 |
Role.objects.get_or_create(name='Role2')
|
... | ... | |
332 |
340 |
assert response.context['user'].roles.count() == 1
|
333 |
341 |
|
334 |
342 |
|
335 |
|
@pytest.mark.django_db
|
336 |
|
def test_group_su(slapd, settings, client):
|
|
343 |
def test_group_su(slapd, settings, client, db):
|
337 |
344 |
from django.contrib.auth.models import Group
|
338 |
345 |
|
339 |
346 |
settings.LDAP_AUTH_SETTINGS = [{
|
... | ... | |
351 |
358 |
assert not response.context['user'].is_staff
|
352 |
359 |
|
353 |
360 |
|
354 |
|
@pytest.mark.django_db
|
355 |
|
def test_group_staff(slapd, settings, client):
|
|
361 |
def test_group_staff(slapd, settings, client, db):
|
356 |
362 |
from django.contrib.auth.models import Group
|
357 |
363 |
|
358 |
364 |
settings.LDAP_AUTH_SETTINGS = [{
|
... | ... | |
370 |
376 |
assert not response.context['user'].is_superuser
|
371 |
377 |
|
372 |
378 |
|
373 |
|
@pytest.mark.django_db
|
374 |
|
def test_get_users(slapd, settings):
|
|
379 |
def test_get_users(slapd, settings, db):
|
375 |
380 |
import django.db.models.base
|
376 |
381 |
from types import MethodType
|
377 |
382 |
|
378 |
|
User = get_user_model()
|
379 |
383 |
settings.LDAP_AUTH_SETTINGS = [{
|
380 |
384 |
'url': [slapd.ldap_url],
|
381 |
385 |
'basedn': u'o=ôrga',
|
... | ... | |
434 |
438 |
save.reset_mock()
|
435 |
439 |
bulk_create.reset_mock()
|
436 |
440 |
u = ldap_backend.LDAPUser.objects.create(username=UID.capitalize())
|
437 |
|
eid = ldap_backend.UserExternalId.objects.create(external_id=UID.capitalize(),
|
438 |
|
source='ldap', user=u)
|
|
441 |
ldap_backend.UserExternalId.objects.create(external_id=UID.capitalize(),
|
|
442 |
source='ldap', user=u)
|
439 |
443 |
# set user login time as if he logged in
|
440 |
|
user = ldap_backend.LDAPUser.objects.get(username='%s@ldap'%UID)
|
|
444 |
user = ldap_backend.LDAPUser.objects.get(username='%s@ldap' % UID)
|
441 |
445 |
user.last_login = timezone.now()
|
442 |
446 |
user.save()
|
443 |
447 |
assert ldap_backend.LDAPUser.objects.count() == 102
|
... | ... | |
445 |
449 |
assert len(users) == 101
|
446 |
450 |
assert ldap_backend.LDAPUser.objects.filter(username='%s' % UID.capitalize()).count() == 0
|
447 |
451 |
|
448 |
|
@pytest.mark.django_db
|
449 |
|
def test_set_mandatory_roles(slapd, settings):
|
|
452 |
|
|
453 |
def test_set_mandatory_roles(slapd, settings, db):
|
450 |
454 |
from authentic2.a2_rbac.models import Role
|
451 |
455 |
|
452 |
456 |
Role.objects.get_or_create(name='tech')
|
453 |
457 |
Role.objects.get_or_create(name='admin')
|
454 |
|
User = get_user_model()
|
455 |
458 |
settings.LDAP_AUTH_SETTINGS = [{
|
456 |
459 |
'url': [slapd.ldap_url],
|
457 |
460 |
'basedn': u'o=ôrga',
|
... | ... | |
468 |
471 |
assert User.objects.first().roles.count() == 2
|
469 |
472 |
|
470 |
473 |
|
471 |
|
@pytest.mark.django_db
|
472 |
|
def test_nocreate_mandatory_roles(slapd, settings):
|
473 |
|
User = get_user_model()
|
|
474 |
def test_nocreate_mandatory_roles(slapd, settings, db):
|
474 |
475 |
settings.LDAP_AUTH_SETTINGS = [{
|
475 |
476 |
'url': [slapd.ldap_url],
|
476 |
477 |
'basedn': u'o=ôrga',
|
... | ... | |
542 |
543 |
'basedn': u'o=ôrga',
|
543 |
544 |
'use_tls': False,
|
544 |
545 |
}]
|
545 |
|
User = get_user_model()
|
546 |
546 |
assert User.objects.count() == 0
|
547 |
547 |
# first login
|
548 |
548 |
response = app.get('/login/')
|
... | ... | |
590 |
590 |
'use_tls': False,
|
591 |
591 |
'user_can_change_password': False,
|
592 |
592 |
}]
|
593 |
|
User = get_user_model()
|
594 |
593 |
assert User.objects.count() == 0
|
595 |
594 |
# first login
|
596 |
595 |
response = app.get('/login/')
|
597 |
|
-
|