Projet

Général

Profil

0006-Add-tests-on-LDAP-password-change-reset-with-ppolicy.patch

Benjamin Renard, 10 novembre 2022 23:36

Télécharger (13,3 ko)

Voir les différences:

Subject: [PATCH 6/6] Add tests on LDAP password change/reset with ppolicy

Licence: MIT
 tests/test_ldap.py | 364 +++++++++++++++++++++++++++++++++++++++++----
 tox.ini            |   1 +
 2 files changed, 338 insertions(+), 27 deletions(-)
tests/test_ldap.py
1151 1151
        assert 'LDAP directory refused the password change' in response.text
1152 1152

  
1153 1153

  
1154
def test_user_change_password(slapd, settings, app, db):
1155
    settings.LDAP_AUTH_SETTINGS = [
1156
        {
1157
            'url': [slapd.ldap_url],
1158
            'basedn': 'o=ôrga',
1159
            'use_tls': False,
1160
            'user_can_change_password': True,
1161
        }
1162
    ]
1163
    assert User.objects.count() == 0
1164
    # first login
1165
    response = app.get('/login/')
1166
    response.form['username'] = USERNAME
1167
    response.form['password'] = PASS
1168
    response = response.form.submit('login-password-submit').follow()
1169

  
1170
    response = app.get('/accounts/password/change/')
1171
    response.form['old_password'] = PASS
1172
    response.form['new_password1'] = 'hopAbcde1'
1173
    response.form['new_password2'] = 'hopAbcde1'
1174
    response = response.form.submit().follow()
1175
    assert 'Password changed' in response.text
1176

  
1177

  
1178
def test_login_ppolicy_password_expired(slapd_ppolicy, settings, app, db, caplog):
1179
    settings.LDAP_AUTH_SETTINGS = [
1180
        {
1181
            'url': [slapd_ppolicy.ldap_url],
1182
            'basedn': 'o=ôrga',
1183
            'use_tls': False,
1184
            'user_can_change_password': True,
1185
            'use_controls': True,
1186
        }
1187
    ]
1188
    # Add default ppolicy with pwdMaxAge defined
1189
    pwdMaxAge = 2
1190
    slapd_ppolicy.add_ldif(
1191
        '''
1192
dn: cn=default,ou=ppolicies,o=ôrga
1193
cn: default
1194
objectclass: top
1195
objectclass: device
1196
objectclass: pwdPolicy
1197
objectclass: pwdPolicyChecker
1198
pwdAttribute: userPassword
1199
pwdMaxAge: {pwdMaxAge}
1200
'''.format(
1201
            pwdMaxAge=pwdMaxAge
1202
        )
1203
    )
1204

  
1205
    assert User.objects.count() == 0
1206
    # first login
1207
    response = app.get('/login/')
1208
    response.form['username'] = USERNAME
1209
    response.form['password'] = PASS
1210
    response = response.form.submit('login-password-submit').follow()
1211

  
1212
    password = 'hopAbcde1'
1213
    response = app.get('/accounts/password/change/')
1214
    response.form['old_password'] = PASS
1215
    response.form['new_password1'] = password
1216
    response.form['new_password2'] = password
1217
    response = response.form.submit().follow()
1218
    assert 'Password changed' in response.text
1219

  
1220
    response = response.click('Logout')
1221

  
1222
    time.sleep(pwdMaxAge * 2)
1223

  
1224
    response = app.get('/login/')
1225
    response.form['username'] = USERNAME
1226
    response.form['password'] = password
1227
    response = response.form.submit('login-password-submit').maybe_follow()
1228

  
1229
    assert 'The password expired.' in response
1230

  
1231

  
1232
def test_user_change_password_in_history(slapd_ppolicy, settings, app, db):
1233
    settings.LDAP_AUTH_SETTINGS = [
1234
        {
1235
            'url': [slapd_ppolicy.ldap_url],
1236
            'basedn': 'o=ôrga',
1237
            'use_tls': False,
1238
            'use_controls': True,
1239
            'user_can_change_password': True,
1240
        }
1241
    ]
1242

  
1243
    # Add default ppolicy with pwdInHistory defined
1244
    slapd_ppolicy.add_ldif(
1245
        '''
1246
dn: cn=default,ou=ppolicies,o=ôrga
1247
cn: default
1248
objectclass: top
1249
objectclass: device
1250
objectclass: pwdPolicy
1251
objectclass: pwdPolicyChecker
1252
pwdAttribute: userPassword
1253
pwdMinAge: 0
1254
pwdMaxAge: 0
1255
pwdInHistory: 1
1256
'''
1257
    )
1258

  
1259
    assert User.objects.count() == 0
1260
    # first login
1261
    response = app.get('/login/')
1262
    response.form['username'] = USERNAME
1263
    response.form['password'] = PASS
1264
    response = response.form.submit('login-password-submit').follow()
1265

  
1266
    # change password
1267
    NEW_PASS = 'hopAbcde1'
1268
    response = app.get('/accounts/password/change/')
1269
    response.form['old_password'] = PASS
1270
    response.form['new_password1'] = NEW_PASS
1271
    response.form['new_password2'] = NEW_PASS
1272
    response = response.form.submit().follow()
1273
    assert 'Password changed' in response.text
1274

  
1275
    # change password again
1276
    response = app.get('/accounts/password/change/')
1277
    response.form['old_password'] = NEW_PASS
1278
    response.form['new_password1'] = PASS
1279
    response.form['new_password2'] = PASS
1280
    response = response.form.submit().maybe_follow()
1281

  
1282
    assert 'This password has already been used and can no longer be used.' in response.text
1283

  
1284

  
1285
def test_user_change_password_too_short(slapd_ppolicy, settings, app, db):
1286
    settings.LDAP_AUTH_SETTINGS = [
1287
        {
1288
            'url': [slapd_ppolicy.ldap_url],
1289
            'basedn': 'o=ôrga',
1290
            'use_tls': False,
1291
            'use_controls': True,
1292
            'user_can_change_password': True,
1293
            'ppolicy_dn': 'cn=default,ou=ppolicies,o=ôrga',
1294
        }
1295
    ]
1296

  
1297
    # Add default ppolicy with pwdCheckQuality enabled and pwdMinLength defined
1298
    pwdMinLength = 15
1299
    slapd_ppolicy.add_ldif(
1300
        '''
1301
dn: cn=default,ou=ppolicies,o=ôrga
1302
cn: default
1303
objectclass: top
1304
objectclass: device
1305
objectclass: pwdPolicy
1306
objectclass: pwdPolicyChecker
1307
pwdAttribute: userPassword
1308
pwdCheckQuality: 1
1309
pwdMinLength: {pwdMinLength}
1310
'''.format(
1311
            pwdMinLength=pwdMinLength
1312
        )
1313
    )
1314

  
1315
    assert User.objects.count() == 0
1316
    # first login
1317
    response = app.get('/login/')
1318
    response.form['username'] = USERNAME
1319
    response.form['password'] = PASS
1320
    response = response.form.submit('login-password-submit').follow()
1321

  
1322
    # change password
1323
    NEW_PASS = 'hopAbcde1'
1324
    response = app.get('/accounts/password/change/')
1325
    response.form['old_password'] = PASS
1326
    response.form['new_password1'] = NEW_PASS
1327
    response.form['new_password2'] = NEW_PASS
1328
    response = response.form.submit().maybe_follow()
1329

  
1330
    assert f'The password is too short (minimun length: {pwdMinLength})' in response.text
1331

  
1332

  
1333
def test_user_change_password_too_soon(slapd_ppolicy, settings, app, db):
1334
    settings.LDAP_AUTH_SETTINGS = [
1335
        {
1336
            'url': [slapd_ppolicy.ldap_url],
1337
            'basedn': 'o=ôrga',
1338
            'use_tls': False,
1339
            'use_controls': True,
1340
            'user_can_change_password': True,
1341
        }
1342
    ]
1343

  
1344
    # Add default ppolicy with pwdMinAge defined
1345
    slapd_ppolicy.add_ldif(
1346
        '''
1347
dn: cn=default,ou=ppolicies,o=ôrga
1348
cn: default
1349
objectclass: top
1350
objectclass: device
1351
objectclass: pwdPolicy
1352
objectclass: pwdPolicyChecker
1353
pwdAttribute: userPassword
1354
pwdMinAge: 120
1355
'''
1356
    )
1357

  
1358
    assert User.objects.count() == 0
1359
    # first login
1360
    response = app.get('/login/')
1361
    response.form['username'] = USERNAME
1362
    response.form['password'] = PASS
1363
    response = response.form.submit('login-password-submit').follow()
1364

  
1365
    # change password
1366
    NEW_PASS = 'hopAbcde1'
1367
    response = app.get('/accounts/password/change/')
1368
    response.form['old_password'] = PASS
1369
    response.form['new_password1'] = NEW_PASS
1370
    response.form['new_password2'] = NEW_PASS
1371
    response = response.form.submit().follow()
1372
    assert 'Password changed' in response.text
1373

  
1374
    # change password again
1375
    response = app.get('/accounts/password/change/')
1376
    response.form['old_password'] = NEW_PASS
1377
    NEW_PASS += '1'
1378
    response.form['new_password1'] = NEW_PASS
1379
    response.form['new_password2'] = NEW_PASS
1380
    response = response.form.submit().maybe_follow()
1381

  
1382
    assert 'It is too soon to change the password.' in response.text
1383

  
1384

  
1385
def test_reset_password_must_supply_old_password(slapd_ppolicy, settings, app, db, caplog):
1386
    settings.LDAP_AUTH_SETTINGS = [
1387
        {
1388
            'url': [slapd_ppolicy.ldap_url],
1389
            'binddn': force_str(slapd_ppolicy.root_bind_dn),
1390
            'bindpw': force_str(slapd_ppolicy.root_bind_password),
1391
            'basedn': 'o=ôrga',
1392
            'use_tls': False,
1393
            'use_controls': True,
1394
            'can_reset_password': True,
1395
        }
1396
    ]
1397

  
1398
    # Add default ppolicy with pwdSafeModify enabled
1399
    slapd_ppolicy.add_ldif(
1400
        '''
1401
dn: cn=default,ou=ppolicies,o=ôrga
1402
cn: default
1403
objectclass: top
1404
objectclass: device
1405
objectclass: pwdPolicy
1406
objectclass: pwdPolicyChecker
1407
pwdAttribute: userPassword
1408
pwdSafeModify: TRUE
1409
'''
1410
    )
1411

  
1412
    assert User.objects.count() == 0
1413
    # first login
1414
    response = app.get('/login/')
1415
    response.form['username'] = USERNAME
1416
    response.form['password'] = PASS
1417
    response = response.form.submit('login-password-submit').follow()
1418
    assert User.objects.count() == 1
1419
    assert 'Étienne Michu' in str(response)
1420
    user = User.objects.get()
1421
    assert user.email == EMAIL
1422
    # logout
1423
    response = response.click('Logout').maybe_follow()
1424

  
1425
    # password reset
1426
    response = response.click('Reset it!')
1427
    response.form['email'] = EMAIL
1428
    assert len(mail.outbox) == 0
1429
    response = response.form.submit()
1430
    assert response['Location'].endswith('/instructions/')
1431
    assert len(mail.outbox) == 1
1432
    url = utils.get_link_from_mail(mail.outbox[0])
1433
    relative_url = url.split('testserver')[1]
1434
    response = app.get(relative_url, status=200)
1435
    response.form.set('new_password1', '1234==aA')
1436
    response.form.set('new_password2', '1234==aA')
1437

  
1438
    response = response.form.submit()
1439
    assert 'The old password must be supplied.' in response
1440

  
1441

  
1442
def test_user_change_password_not_allowed(slapd_ppolicy, settings, app, db):
1443
    settings.LDAP_AUTH_SETTINGS = [
1444
        {
1445
            'url': [slapd_ppolicy.ldap_url],
1446
            'basedn': 'o=ôrga',
1447
            'use_tls': False,
1448
            'use_controls': True,
1449
            'user_can_change_password': True,
1450
        }
1451
    ]
1452

  
1453
    # Add default ppolicy with pwdAllowUserChange disabled
1454
    slapd_ppolicy.add_ldif(
1455
        '''
1456
dn: cn=default,ou=ppolicies,o=ôrga
1457
cn: default
1458
objectclass: top
1459
objectclass: device
1460
objectclass: pwdPolicy
1461
objectclass: pwdPolicyChecker
1462
pwdAttribute: userPassword
1463
pwdAllowUserChange: FALSE
1464
'''
1465
    )
1466

  
1467
    assert User.objects.count() == 0
1468
    # first login
1469
    response = app.get('/login/')
1470
    response.form['username'] = USERNAME
1471
    response.form['password'] = PASS
1472
    response = response.form.submit('login-password-submit').follow()
1473

  
1474
    # change password
1475
    NEW_PASS = 'hopAbcde1'
1476
    response = app.get('/accounts/password/change/')
1477
    response.form['old_password'] = PASS
1478
    response.form['new_password1'] = NEW_PASS
1479
    response.form['new_password2'] = NEW_PASS
1480
    response = response.form.submit().maybe_follow()
1481

  
1482
    assert 'It is not possible to modify the password.' in response.text
1483

  
1484

  
1154 1485
def test_tls(db, tls_slapd, settings, client):
1155 1486
    conn = tls_slapd.get_connection_admin()
1156 1487
    conn.modify_s(
......
1374 1705
            'basedn': 'o=ôrga',
1375 1706
            'use_tls': False,
1376 1707
            'use_controls': True,
1708
            'ppolicy_dn': 'cn=default,ou=ppolicies,o=ôrga',
1377 1709
        }
1378 1710
    ]
1379 1711

  
......
1418 1750
    response.form.set('username', USERNAME)
1419 1751
    response.form.set('password', 'invalid')
1420 1752
    response = response.form.submit(name='login-password-submit')
1421
    assert 'account is locked' in str(response.pyquery('.messages'))
1753

  
1754
    assert 'account is locked since ' in str(response.pyquery('.messages'))
1755
    assert f'after {pwdMaxFailure} failures' in str(response.pyquery('.messages'))
1422 1756

  
1423 1757

  
1424 1758
def ppolicy_authenticate_exactly_pwdMaxFailure(slapd_ppolicy, caplog):
......
1623 1957
        }
1624 1958
    ]
1625 1959

  
1960
    # Add default ppolicy with pwdMaxAge and pwdExpireWarning defined
1626 1961
    pwdMaxAge = 3600
1627 1962
    slapd_ppolicy.add_ldif(
1628 1963
        '''
......
1633 1968
objectclass: pwdPolicy
1634 1969
objectclass: pwdPolicyChecker
1635 1970
pwdAttribute: userPassword
1636
pwdMinAge: 0
1637 1971
pwdMaxAge: {pwdMaxAge}
1638
pwdInHistory: 1
1639
pwdCheckQuality: 0
1640
pwdMinLength: 0
1641 1972
pwdExpireWarning: {pwdMaxAge}
1642
pwdGraceAuthnLimit: 0
1643
pwdLockout: TRUE
1644
pwdLockoutDuration: 0
1645
pwdMaxFailure: 0
1646
pwdMaxRecordedFailure: 0
1647
pwdFailureCountInterval: 0
1648
pwdMustChange: FALSE
1649
pwdAllowUserChange: TRUE
1650
pwdSafeModify: FALSE
1651 1973
'''.format(
1652 1974
            pwdMaxAge=pwdMaxAge
1653 1975
        )
......
1679 2001
        }
1680 2002
    ]
1681 2003

  
2004
    # Add default ppolicy with pwdMaxAge and pwdExpireWarning defined
1682 2005
    pwdMaxAge = 3600
1683 2006
    slapd_ppolicy.add_ldif(
1684 2007
        '''
......
1689 2012
objectclass: pwdPolicy
1690 2013
objectclass: pwdPolicyChecker
1691 2014
pwdAttribute: userPassword
1692
pwdMinAge: 0
1693 2015
pwdMaxAge: {pwdMaxAge}
1694
pwdInHistory: 1
1695
pwdCheckQuality: 0
1696
pwdMinLength: 0
1697 2016
pwdExpireWarning: {pwdMaxAge}
1698
pwdGraceAuthnLimit: 0
1699
pwdLockout: TRUE
1700
pwdLockoutDuration: 0
1701
pwdMaxFailure: 0
1702
pwdMaxRecordedFailure: 0
1703
pwdFailureCountInterval: 0
1704
pwdMustChange: FALSE
1705
pwdAllowUserChange: TRUE
1706
pwdSafeModify: FALSE
1707 2017
'''.format(
1708 2018
            pwdMaxAge=pwdMaxAge
1709 2019
        )
tox.ini
92 92
  uwsgidecorators
93 93
  enum34<=1.1.6
94 94
  ldaptools>=0.24
95
  python-ldap>=3.3.1
95 96
  numpy
96 97
  django-filter
97 98
  buster: djangorestframework>=3.9.2,<3.10
98
-