|
|
b8da0b |
From 6a741b3ef50babf2ac2479437a38829204ffd438 Mon Sep 17 00:00:00 2001
|
|
|
b8da0b |
From: tbordaz <tbordaz@redhat.com>
|
|
|
b8da0b |
Date: Thu, 17 Jun 2021 16:22:09 +0200
|
|
|
b8da0b |
Subject: [PATCH] Issue 4788 - CLI should support Temporary Password Rules
|
|
|
b8da0b |
attributes (#4793)
|
|
|
b8da0b |
|
|
|
b8da0b |
Bug description:
|
|
|
b8da0b |
Since #4725, password policy support temporary password rules.
|
|
|
b8da0b |
CLI (dsconf) does not support this RFE and only direct ldap
|
|
|
b8da0b |
operation can configure global/local password policy
|
|
|
b8da0b |
|
|
|
b8da0b |
Fix description:
|
|
|
b8da0b |
Update dsconf to support this new RFE.
|
|
|
b8da0b |
To run successfully the testcase it relies on #4788
|
|
|
b8da0b |
|
|
|
b8da0b |
relates: #4788
|
|
|
b8da0b |
|
|
|
b8da0b |
Reviewed by: Simon Pichugin (thanks !!)
|
|
|
b8da0b |
|
|
|
b8da0b |
Platforms tested: F34
|
|
|
b8da0b |
---
|
|
|
b8da0b |
.../password/pwdPolicy_attribute_test.py | 172 ++++++++++++++++--
|
|
|
b8da0b |
src/lib389/lib389/cli_conf/pwpolicy.py | 5 +-
|
|
|
b8da0b |
src/lib389/lib389/pwpolicy.py | 5 +-
|
|
|
b8da0b |
3 files changed, 165 insertions(+), 17 deletions(-)
|
|
|
b8da0b |
|
|
|
b8da0b |
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
b8da0b |
index aee3a91ad..085d0a373 100644
|
|
|
b8da0b |
--- a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
b8da0b |
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
b8da0b |
@@ -34,7 +34,7 @@ log = logging.getLogger(__name__)
|
|
|
b8da0b |
|
|
|
b8da0b |
|
|
|
b8da0b |
@pytest.fixture(scope="module")
|
|
|
b8da0b |
-def create_user(topology_st, request):
|
|
|
b8da0b |
+def test_user(topology_st, request):
|
|
|
b8da0b |
"""User for binding operation"""
|
|
|
b8da0b |
topology_st.standalone.config.set('nsslapd-auditlog-logging-enabled', 'on')
|
|
|
b8da0b |
log.info('Adding test user {}')
|
|
|
b8da0b |
@@ -56,10 +56,11 @@ def create_user(topology_st, request):
|
|
|
b8da0b |
topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
+ return user
|
|
|
b8da0b |
|
|
|
b8da0b |
|
|
|
b8da0b |
@pytest.fixture(scope="module")
|
|
|
b8da0b |
-def password_policy(topology_st, create_user):
|
|
|
b8da0b |
+def password_policy(topology_st, test_user):
|
|
|
b8da0b |
"""Set up password policy for subtree and user"""
|
|
|
b8da0b |
|
|
|
b8da0b |
pwp = PwPolicyManager(topology_st.standalone)
|
|
|
b8da0b |
@@ -71,7 +72,7 @@ def password_policy(topology_st, create_user):
|
|
|
b8da0b |
pwp.create_user_policy(TEST_USER_DN, policy_props)
|
|
|
b8da0b |
|
|
|
b8da0b |
@pytest.mark.skipif(ds_is_older('1.4.3.3'), reason="Not implemented")
|
|
|
b8da0b |
-def test_pwd_reset(topology_st, create_user):
|
|
|
b8da0b |
+def test_pwd_reset(topology_st, test_user):
|
|
|
b8da0b |
"""Test new password policy attribute "pwdReset"
|
|
|
b8da0b |
|
|
|
b8da0b |
:id: 03db357b-4800-411e-a36e-28a534293004
|
|
|
b8da0b |
@@ -124,7 +125,7 @@ def test_pwd_reset(topology_st, create_user):
|
|
|
b8da0b |
[('on', 'off', ldap.UNWILLING_TO_PERFORM),
|
|
|
b8da0b |
('off', 'off', ldap.UNWILLING_TO_PERFORM),
|
|
|
b8da0b |
('off', 'on', False), ('on', 'on', False)])
|
|
|
b8da0b |
-def test_change_pwd(topology_st, create_user, password_policy,
|
|
|
b8da0b |
+def test_change_pwd(topology_st, test_user, password_policy,
|
|
|
b8da0b |
subtree_pwchange, user_pwchange, exception):
|
|
|
b8da0b |
"""Verify that 'passwordChange' attr works as expected
|
|
|
b8da0b |
User should have a priority over a subtree.
|
|
|
b8da0b |
@@ -184,7 +185,7 @@ def test_change_pwd(topology_st, create_user, password_policy,
|
|
|
b8da0b |
user.reset_password(TEST_USER_PWD)
|
|
|
b8da0b |
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_pwd_min_age(topology_st, create_user, password_policy):
|
|
|
b8da0b |
+def test_pwd_min_age(topology_st, test_user, password_policy):
|
|
|
b8da0b |
"""If we set passwordMinAge to some value, for example to 10, then it
|
|
|
b8da0b |
should not allow the user to change the password within 10 seconds after
|
|
|
b8da0b |
his previous change.
|
|
|
b8da0b |
@@ -257,7 +258,7 @@ def test_pwd_min_age(topology_st, create_user, password_policy):
|
|
|
b8da0b |
topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
user.reset_password(TEST_USER_PWD)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_maxuse_1(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_maxuse_1(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRMaxUse
|
|
|
b8da0b |
Test that after passwordTPRMaxUse failures to bind
|
|
|
b8da0b |
additional bind with valid password are failing with CONSTRAINT_VIOLATION
|
|
|
b8da0b |
@@ -374,7 +375,7 @@ def test_global_tpr_maxuse_1(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_maxuse_2(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_maxuse_2(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRMaxUse
|
|
|
b8da0b |
Test that after less than passwordTPRMaxUse failures to bind
|
|
|
b8da0b |
additional bind with valid password are successfull
|
|
|
b8da0b |
@@ -474,7 +475,7 @@ def test_global_tpr_maxuse_2(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_maxuse_3(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_maxuse_3(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRMaxUse
|
|
|
b8da0b |
Test that after less than passwordTPRMaxUse failures to bind
|
|
|
b8da0b |
A bind with valid password is successfull but passwordMustChange
|
|
|
b8da0b |
@@ -587,7 +588,7 @@ def test_global_tpr_maxuse_3(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_maxuse_4(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_maxuse_4(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRMaxUse
|
|
|
b8da0b |
Test that a TPR attribute passwordTPRMaxUse
|
|
|
b8da0b |
can be updated by DM but not the by user itself
|
|
|
b8da0b |
@@ -701,7 +702,148 @@ def test_global_tpr_maxuse_4(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayValidFrom_1(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_local_tpr_maxuse_5(topology_st, test_user, request):
|
|
|
b8da0b |
+ """Test TPR local policy overpass global one: passwordTPRMaxUse
|
|
|
b8da0b |
+ Test that after passwordTPRMaxUse failures to bind
|
|
|
b8da0b |
+ additional bind with valid password are failing with CONSTRAINT_VIOLATION
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ :id: c3919707-d804-445a-8754-8385b1072c42
|
|
|
b8da0b |
+ :customerscenario: False
|
|
|
b8da0b |
+ :setup: Standalone instance
|
|
|
b8da0b |
+ :steps:
|
|
|
b8da0b |
+ 1. Global password policy Enable passwordMustChange
|
|
|
b8da0b |
+ 2. Global password policy Set passwordTPRMaxUse=5
|
|
|
b8da0b |
+ 3. Global password policy Set passwordMaxFailure to a higher value to not disturb the test
|
|
|
b8da0b |
+ 4. Local password policy Enable passwordMustChange
|
|
|
b8da0b |
+ 5. Local password policy Set passwordTPRMaxUse=10 (higher than global)
|
|
|
b8da0b |
+ 6. Bind with a wrong password 10 times and check INVALID_CREDENTIALS
|
|
|
b8da0b |
+ 7. Check that passwordTPRUseCount got to the limit (5)
|
|
|
b8da0b |
+ 8. Bind with a wrong password (CONSTRAINT_VIOLATION)
|
|
|
b8da0b |
+ and check passwordTPRUseCount overpass the limit by 1 (11)
|
|
|
b8da0b |
+ 9. Bind with a valid password 10 times and check CONSTRAINT_VIOLATION
|
|
|
b8da0b |
+ and check passwordTPRUseCount increases
|
|
|
b8da0b |
+ 10. Reset password policy configuration and remove local password from user
|
|
|
b8da0b |
+ :expected results:
|
|
|
b8da0b |
+ 1. Success
|
|
|
b8da0b |
+ 2. Success
|
|
|
b8da0b |
+ 3. Success
|
|
|
b8da0b |
+ 4. Success
|
|
|
b8da0b |
+ 5. Success
|
|
|
b8da0b |
+ 6. Success
|
|
|
b8da0b |
+ 7. Success
|
|
|
b8da0b |
+ 8. Success
|
|
|
b8da0b |
+ 9. Success
|
|
|
b8da0b |
+ 10. Success
|
|
|
b8da0b |
+ """
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ global_tpr_maxuse = 5
|
|
|
b8da0b |
+ # Set global password policy config, passwordMaxFailure being higher than
|
|
|
b8da0b |
+ # passwordTPRMaxUse so that TPR is enforced first
|
|
|
b8da0b |
+ topology_st.standalone.config.replace('passwordMustChange', 'on')
|
|
|
b8da0b |
+ topology_st.standalone.config.replace('passwordMaxFailure', str(global_tpr_maxuse + 20))
|
|
|
b8da0b |
+ topology_st.standalone.config.replace('passwordTPRMaxUse', str(global_tpr_maxuse))
|
|
|
b8da0b |
+ time.sleep(.5)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ local_tpr_maxuse = global_tpr_maxuse + 5
|
|
|
b8da0b |
+ # Reset user's password with a local password policy
|
|
|
b8da0b |
+ # that has passwordTPRMaxUse higher than global
|
|
|
b8da0b |
+ #our_user = UserAccount(topology_st.standalone, TEST_USER_DN)
|
|
|
b8da0b |
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
|
|
|
b8da0b |
+ 'slapd-standalone1',
|
|
|
b8da0b |
+ 'localpwp',
|
|
|
b8da0b |
+ 'adduser',
|
|
|
b8da0b |
+ test_user.dn])
|
|
|
b8da0b |
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
|
|
|
b8da0b |
+ 'slapd-standalone1',
|
|
|
b8da0b |
+ 'localpwp',
|
|
|
b8da0b |
+ 'set',
|
|
|
b8da0b |
+ '--pwptprmaxuse',
|
|
|
b8da0b |
+ str(local_tpr_maxuse),
|
|
|
b8da0b |
+ '--pwdmustchange',
|
|
|
b8da0b |
+ 'on',
|
|
|
b8da0b |
+ test_user.dn])
|
|
|
b8da0b |
+ test_user.replace('userpassword', PASSWORD)
|
|
|
b8da0b |
+ time.sleep(.5)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # look up to passwordTPRMaxUse with failing
|
|
|
b8da0b |
+ # bind to check that the limits of TPR are enforced
|
|
|
b8da0b |
+ for i in range(local_tpr_maxuse):
|
|
|
b8da0b |
+ # Bind as user with a wrong password
|
|
|
b8da0b |
+ with pytest.raises(ldap.INVALID_CREDENTIALS):
|
|
|
b8da0b |
+ test_user.rebind('wrong password')
|
|
|
b8da0b |
+ time.sleep(.5)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdReset is TRUE
|
|
|
b8da0b |
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
+ #assert test_user.get_attr_val_utf8('pwdReset') == 'TRUE'
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdTPRReset is TRUE
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(i+1)
|
|
|
b8da0b |
+ log.info("%dth failing bind (INVALID_CREDENTIALS) => pwdTPRUseCount = %d" % (i+1, i+1))
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Now the #failures reached passwordTPRMaxUse
|
|
|
b8da0b |
+ # Check that pwdReset is TRUE
|
|
|
b8da0b |
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdTPRReset is TRUE
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse)
|
|
|
b8da0b |
+ log.info("last failing bind (INVALID_CREDENTIALS) => pwdTPRUseCount = %d" % (local_tpr_maxuse))
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Bind as user with wrong password --> ldap.CONSTRAINT_VIOLATION
|
|
|
b8da0b |
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
|
|
|
b8da0b |
+ test_user.rebind("wrong password")
|
|
|
b8da0b |
+ time.sleep(.5)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdReset is TRUE
|
|
|
b8da0b |
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdTPRReset is TRUE
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse + 1)
|
|
|
b8da0b |
+ log.info("failing bind (CONSTRAINT_VIOLATION) => pwdTPRUseCount = %d" % (local_tpr_maxuse + i))
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Now check that all next attempts with correct password are all in LDAP_CONSTRAINT_VIOLATION
|
|
|
b8da0b |
+ # and passwordTPRRetryCount remains unchanged
|
|
|
b8da0b |
+ # account is now similar to locked
|
|
|
b8da0b |
+ for i in range(10):
|
|
|
b8da0b |
+ # Bind as user with valid password
|
|
|
b8da0b |
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
|
|
|
b8da0b |
+ test_user.rebind(PASSWORD)
|
|
|
b8da0b |
+ time.sleep(.5)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdReset is TRUE
|
|
|
b8da0b |
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Check that pwdTPRReset is TRUE
|
|
|
b8da0b |
+ # pwdTPRUseCount keeps increasing
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRReset') == 'TRUE'
|
|
|
b8da0b |
+ assert test_user.get_attr_val_utf8('pwdTPRUseCount') == str(local_tpr_maxuse + i + 2)
|
|
|
b8da0b |
+ log.info("Rejected bind (CONSTRAINT_VIOLATION) => pwdTPRUseCount = %d" % (local_tpr_maxuse + i + 2))
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ def fin():
|
|
|
b8da0b |
+ topology_st.standalone.restart()
|
|
|
b8da0b |
+ # Reset password policy config
|
|
|
b8da0b |
+ topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
b8da0b |
+ topology_st.standalone.config.replace('passwordMustChange', 'off')
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Remove local password policy from that entry
|
|
|
b8da0b |
+ subprocess.call(['%s/dsconf' % topology_st.standalone.get_sbin_dir(),
|
|
|
b8da0b |
+ 'slapd-standalone1',
|
|
|
b8da0b |
+ 'localpwp',
|
|
|
b8da0b |
+ 'remove',
|
|
|
b8da0b |
+ test_user.dn])
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ # Reset user's password
|
|
|
b8da0b |
+ test_user.replace('userpassword', TEST_USER_PWD)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+ request.addfinalizer(fin)
|
|
|
b8da0b |
+
|
|
|
b8da0b |
+def test_global_tpr_delayValidFrom_1(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayValidFrom
|
|
|
b8da0b |
Test that a TPR password is not valid before reset time +
|
|
|
b8da0b |
passwordTPRDelayValidFrom
|
|
|
b8da0b |
@@ -766,7 +908,7 @@ def test_global_tpr_delayValidFrom_1(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayValidFrom_2(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_delayValidFrom_2(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayValidFrom
|
|
|
b8da0b |
Test that a TPR password is valid after reset time +
|
|
|
b8da0b |
passwordTPRDelayValidFrom
|
|
|
b8da0b |
@@ -838,7 +980,7 @@ def test_global_tpr_delayValidFrom_2(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayValidFrom_3(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_delayValidFrom_3(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayValidFrom
|
|
|
b8da0b |
Test that a TPR attribute passwordTPRDelayValidFrom
|
|
|
b8da0b |
can be updated by DM but not the by user itself
|
|
|
b8da0b |
@@ -940,7 +1082,7 @@ def test_global_tpr_delayValidFrom_3(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayExpireAt_1(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_delayExpireAt_1(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayExpireAt
|
|
|
b8da0b |
Test that a TPR password is not valid after reset time +
|
|
|
b8da0b |
passwordTPRDelayExpireAt
|
|
|
b8da0b |
@@ -1010,7 +1152,7 @@ def test_global_tpr_delayExpireAt_1(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayExpireAt_2(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_delayExpireAt_2(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayExpireAt
|
|
|
b8da0b |
Test that a TPR password is valid before reset time +
|
|
|
b8da0b |
passwordTPRDelayExpireAt
|
|
|
b8da0b |
@@ -1082,7 +1224,7 @@ def test_global_tpr_delayExpireAt_2(topology_st, create_user, request):
|
|
|
b8da0b |
|
|
|
b8da0b |
request.addfinalizer(fin)
|
|
|
b8da0b |
|
|
|
b8da0b |
-def test_global_tpr_delayExpireAt_3(topology_st, create_user, request):
|
|
|
b8da0b |
+def test_global_tpr_delayExpireAt_3(topology_st, test_user, request):
|
|
|
b8da0b |
"""Test global TPR policy : passwordTPRDelayExpireAt
|
|
|
b8da0b |
Test that a TPR attribute passwordTPRDelayExpireAt
|
|
|
b8da0b |
can be updated by DM but not the by user itself
|
|
|
b8da0b |
diff --git a/src/lib389/lib389/cli_conf/pwpolicy.py b/src/lib389/lib389/cli_conf/pwpolicy.py
|
|
|
b8da0b |
index 2838afcb8..26af6e7ec 100644
|
|
|
b8da0b |
--- a/src/lib389/lib389/cli_conf/pwpolicy.py
|
|
|
b8da0b |
+++ b/src/lib389/lib389/cli_conf/pwpolicy.py
|
|
|
b8da0b |
@@ -255,6 +255,9 @@ def create_parser(subparsers):
|
|
|
b8da0b |
set_parser.add_argument('--pwpinheritglobal', help="Set to \"on\" to allow local policies to inherit the global policy")
|
|
|
b8da0b |
set_parser.add_argument('--pwddictcheck', help="Set to \"on\" to enforce CrackLib dictionary checking")
|
|
|
b8da0b |
set_parser.add_argument('--pwddictpath', help="Filesystem path to specific/custom CrackLib dictionary files")
|
|
|
b8da0b |
+ set_parser.add_argument('--pwptprmaxuse', help="Number of times a reset password can be used for authentication")
|
|
|
b8da0b |
+ set_parser.add_argument('--pwptprdelayexpireat', help="Number of seconds after which a reset password expires")
|
|
|
b8da0b |
+ set_parser.add_argument('--pwptprdelayvalidfrom', help="Number of seconds to wait before using a reset password to authenticated")
|
|
|
b8da0b |
# delete local password policy
|
|
|
b8da0b |
del_parser = local_subcommands.add_parser('remove', help='Remove a local password policy')
|
|
|
b8da0b |
del_parser.set_defaults(func=del_local_policy)
|
|
|
b8da0b |
@@ -291,4 +294,4 @@ def create_parser(subparsers):
|
|
|
b8da0b |
#############################################
|
|
|
b8da0b |
set_parser.add_argument('DN', nargs=1, help='Set the local policy for this entry DN')
|
|
|
b8da0b |
add_subtree_parser.add_argument('DN', nargs=1, help='Add/replace the subtree policy for this entry DN')
|
|
|
b8da0b |
- add_user_parser.add_argument('DN', nargs=1, help='Add/replace the local password policy for this entry DN')
|
|
|
b8da0b |
\ No newline at end of file
|
|
|
b8da0b |
+ add_user_parser.add_argument('DN', nargs=1, help='Add/replace the local password policy for this entry DN')
|
|
|
b8da0b |
diff --git a/src/lib389/lib389/pwpolicy.py b/src/lib389/lib389/pwpolicy.py
|
|
|
b8da0b |
index 8653cb195..d2427933b 100644
|
|
|
b8da0b |
--- a/src/lib389/lib389/pwpolicy.py
|
|
|
b8da0b |
+++ b/src/lib389/lib389/pwpolicy.py
|
|
|
b8da0b |
@@ -65,7 +65,10 @@ class PwPolicyManager(object):
|
|
|
b8da0b |
'pwddictcheck': 'passworddictcheck',
|
|
|
b8da0b |
'pwddictpath': 'passworddictpath',
|
|
|
b8da0b |
'pwdallowhash': 'nsslapd-allow-hashed-passwords',
|
|
|
b8da0b |
- 'pwpinheritglobal': 'nsslapd-pwpolicy-inherit-global'
|
|
|
b8da0b |
+ 'pwpinheritglobal': 'nsslapd-pwpolicy-inherit-global',
|
|
|
b8da0b |
+ 'pwptprmaxuse': 'passwordTPRMaxUse',
|
|
|
b8da0b |
+ 'pwptprdelayexpireat': 'passwordTPRDelayExpireAt',
|
|
|
b8da0b |
+ 'pwptprdelayvalidfrom': 'passwordTPRDelayValidFrom'
|
|
|
b8da0b |
}
|
|
|
b8da0b |
|
|
|
b8da0b |
def is_subtree_policy(self, dn):
|
|
|
b8da0b |
--
|
|
|
b8da0b |
2.31.1
|
|
|
b8da0b |
|