From 2813d3d0d524488bea30412a9289e0273f049936 Mon Sep 17 00:00:00 2001
From: Anuj Borah <aborah@redhat.com>
Date: Jun 22 2020 13:55:09 +0000
Subject: Issue:50860 - Port Password Policy test cases from TET to python3 part2


Bug Description:  CI test - Port Password Policy test cases from TET to python3 part2

Relates: https://pagure.io/389-ds-base/issue/50860

Author: aborah

Reviewed by: Viktor Ashirov

---

diff --git a/dirsrvtests/tests/suites/password/password_policy_test.py b/dirsrvtests/tests/suites/password/password_policy_test.py
index aa01b5a..59432e5 100644
--- a/dirsrvtests/tests/suites/password/password_policy_test.py
+++ b/dirsrvtests/tests/suites/password/password_policy_test.py
@@ -12,6 +12,7 @@ This test script will test password policy.
 
 import os
 import pytest
+import time
 from lib389.topologies import topology_st as topo
 from lib389.idm.organizationalunit import OrganizationalUnits
 from lib389.idm.user import UserAccounts, UserAccount
@@ -115,6 +116,20 @@ def change_password_with_admin(topo, user_password_new_pass_list):
         UserAccount(topo.standalone, f'{user},{DEFAULT_SUFFIX}').replace('userpassword', password)
 
 
+def _do_transaction_for_pwp(topo, attr1, attr2):
+    """
+    Will change pwp parameters
+    """
+    pwp = PwPolicyManager(topo.standalone)
+    orl = pwp.get_pwpolicy_entry(f'uid=orla,ou=dirsec,{DEFAULT_SUFFIX}')
+    joe = pwp.get_pwpolicy_entry(f'uid=joe,ou=people,{DEFAULT_SUFFIX}')
+    people = pwp.get_pwpolicy_entry(f'ou=people,{DEFAULT_SUFFIX}')
+    for instance in [orl, joe, people]:
+        instance.replace(attr1, attr2)
+    for instance in [orl, joe, people]:
+        assert instance.get_attr_val_utf8(attr1) == attr2
+
+
 @pytest.fixture(scope="function")
 def _fixture_for_password_change(request, topo):
     pwp = PwPolicyManager(topo.standalone)
@@ -614,6 +629,287 @@ def test_password_syntax_section(topo, _policy_setup, _fixture_for_syntax_sectio
     ])
 
 
+@pytest.fixture(scope="function")
+def _fixture_for_password_history(request, topo):
+    pwp = PwPolicyManager(topo.standalone)
+    orl = pwp.get_pwpolicy_entry(f'uid=orla,ou=dirsec,{DEFAULT_SUFFIX}')
+    joe = pwp.get_pwpolicy_entry(f'uid=joe,ou=people,{DEFAULT_SUFFIX}')
+    people = pwp.get_pwpolicy_entry(f'ou=people,{DEFAULT_SUFFIX}')
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p1')
+    ])
+    for instance in [orl, joe, people]:
+        instance.replace_many(
+            ('passwordhistory', 'on'),
+            ('passwordinhistory', '3'),
+            ('passwordChange', 'on'))
+    for instance in [orl, joe, people]:
+        assert instance.get_attr_val_utf8('passwordhistory') == 'on'
+        assert instance.get_attr_val_utf8('passwordinhistory') == '3'
+        assert instance.get_attr_val_utf8('passwordChange') == 'on'
+
+    def final_step():
+        for instance1 in [orl, joe, people]:
+            instance1.replace('passwordhistory', 'off')
+        change_password_with_admin(topo, [
+            ('uid=orla,ou=dirsec', '000rLb1'),
+            ('uid=joe,ou=people', '00J0e1'),
+            ('uid=jack,ou=people', '00J6ck1'),
+            ('uid=deep,ou=others,ou=people', '00De3p1')
+        ])
+    request.addfinalizer(final_step)
+
+
+def test_password_history_section(topo, _policy_setup, _fixture_for_password_history):
+    """ Password History Section.
+
+        :id: 51f459a0-a0ba-11ea-ade7-8c16451d917b
+        :setup: Standalone
+        :steps:
+            1. Changing current password for orla,joe,jack and deep
+            2. Checking that the passwordhistory attribute has been added !
+            3. Try to change the password back which should fail
+            4. Change the passwords for all four test users to something new
+            5. Try to change passwords back to the first password
+            6. Change to a fourth password not in password history
+            7. Try to change all the passwords back to the first password
+            8. Change the password to one more new password as root dn
+            9. Now try to change the password back to the first password
+            10. Checking that password history does still containt the previous 3 passwords
+            11. Add a password test for long long password (more than 490 bytes).
+            12. Changing password : LONGPASSWORD goes in history
+            13. Setting policy to NOT keep password histories
+            14. Changing current password from *2 to *2
+            15. Try to change *2 to *1, should succeed
+        :expected results:
+            1. Success
+            2. Success
+            3. Fail
+            4. Success
+            5. Fail
+            6. Success
+            7. Fail
+            8. Success
+            9. Success
+            10. Success
+            11. Success
+            12. Success
+            13. Success
+            14. Success
+            15. Success
+    """
+    # Changing current password for orla,joe,jack and deep
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb2'),
+        ('uid=joe,ou=people', '00J0e2'),
+        ('uid=jack,ou=people', '00J6ck2'),
+        ('uid=deep,ou=others,ou=people', '00De3p2'),
+    ])
+    time.sleep(1)
+    # Checking that the password history attribute has been added !
+    for user, password in [
+        ('uid=orla,ou=dirsec', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p1'),
+    ]:
+        assert password in UserAccount(topo.standalone,
+                                       f'{user},{DEFAULT_SUFFIX}').get_attr_val_utf8("passwordhistory")
+    # Try to change the password back which should fail
+    with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+        change_password(topo, [
+            ('uid=orla,ou=dirsec', '000rLb2', '000rLb1'),
+            ('uid=joe,ou=people', '00J0e2', '00J0e1'),
+            ('uid=jack,ou=people', '00J6ck2', '00J6ck1'),
+            ('uid=deep,ou=others,ou=people', '00De3p2', '00De3p1'),
+        ])
+    # Change the passwords for all four test users to something new
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb3'),
+        ('uid=joe,ou=people', '00J0e3'),
+        ('uid=jack,ou=people', '00J6ck3'),
+        ('uid=deep,ou=others,ou=people', '00De3p3')
+    ])
+    # Try to change passwords back to the first password
+    time.sleep(1)
+    with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+        change_password(topo, [
+            ('uid=orla,ou=dirsec', '000rLb3', '000rLb1'),
+            ('uid=joe,ou=people', '00J0e3', '00J0e1'),
+            ('uid=jack,ou=people', '00J6ck3', '00J6ck1'),
+            ('uid=deep,ou=others,ou=people', '00De3p3', '00De3p1'),
+        ])
+    # Change to a fourth password not in password history
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb4'),
+        ('uid=joe,ou=people', '00J0e4'),
+        ('uid=jack,ou=people', '00J6ck4'),
+        ('uid=deep,ou=others,ou=people', '00De3p4')
+    ])
+    time.sleep(1)
+    # Try to change all the passwords back to the first password
+    with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+        change_password(topo, [
+            ('uid=orla,ou=dirsec', '000rLb4', '000rLb1'),
+            ('uid=joe,ou=people', '00J0e4', '00J0e1'),
+            ('uid=jack,ou=people', '00J6ck4', '00J6ck1'),
+            ('uid=deep,ou=others,ou=people', '00De3p4', '00De3p1')
+        ])
+    # change the password to one more new password as root dn
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb5'),
+        ('uid=joe,ou=people', '00J0e5'),
+        ('uid=jack,ou=people', '00J6ck5'),
+        ('uid=deep,ou=others,ou=people', '00De3p5')
+    ])
+    time.sleep(1)
+    # Now try to change the password back to the first password
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb5', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e5', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck5', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p5', '00De3p1')
+    ])
+    time.sleep(1)
+    # checking that password history does still containt the previous 3 passwords
+    for user, password3, password2, password1 in [
+        ('uid=orla,ou=dirsec', '000rLb5', '000rLb4', '000rLb3'),
+        ('uid=joe,ou=people', '00J0e5', '00J0e4', '00J0e3'),
+        ('uid=jack,ou=people', '00J6ck5', '00J6ck4', '00J6ck3'),
+        ('uid=deep,ou=others,ou=people', '00De3p5', '00De3p4', '00De3p3')
+    ]:
+        user1 = UserAccount(topo.standalone, f'{user},{DEFAULT_SUFFIX}')
+        pass_list = ''.join(user1.get_attr_vals_utf8("passwordhistory"))
+        assert password1 in pass_list
+        assert password2 in pass_list
+        assert password3 in pass_list
+    # Add a password test for long long password (more than 490 bytes).
+    long = '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901' \
+           '23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456' \
+           '789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012' \
+           '345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678' \
+           '901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234' \
+           '5678901234567890123456789LENGTH=510'
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb1', long),
+        ('uid=joe,ou=people', '00J0e1', long),
+        ('uid=jack,ou=people', '00J6ck1', long),
+        ('uid=deep,ou=others,ou=people', '00De3p1', long)
+    ])
+    time.sleep(1)
+    # Changing password : LONGPASSWORD goes in history
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', long, '000rLb2'),
+        ('uid=joe,ou=people', long, '00J0e2'),
+        ('uid=jack,ou=people', long, '00J6ck2'),
+        ('uid=deep,ou=others,ou=people', long, '00De3p2')
+    ])
+    time.sleep(1)
+    for user, password in [
+        ('uid=orla,ou=dirsec', '000rLb2'),
+        ('uid=joe,ou=people', '00J0e2'),
+        ('uid=jack,ou=people', '00J6ck2'),
+        ('uid=deep,ou=others,ou=people', '00De3p2')
+    ]:
+        real_user = UserAccount(topo.standalone, f'{user},{DEFAULT_SUFFIX}')
+        conn = real_user.bind(password)
+        assert long in ''.join(UserAccount(conn,
+                                           f'{user},{DEFAULT_SUFFIX}').get_attr_vals_utf8("passwordhistory"))
+    # Setting policy to NOT keep password histories
+    _do_transaction_for_pwp(topo, 'passwordhistory', 'off')
+    time.sleep(1)
+    # Changing current password from *2 to *2
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb2', '000rLb2'),
+        ('uid=joe,ou=people', '00J0e2', '00J0e2'),
+        ('uid=jack,ou=people', '00J6ck2', '00J6ck2'),
+        ('uid=deep,ou=others,ou=people', '00De3p2', '00De3p2')
+    ])
+    # Try to change *2 to *1, should succeed
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb2', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e2', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck2', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p2', '00De3p1')
+    ])
+
+
+@pytest.fixture(scope="function")
+def _fixture_for_password_min_age(request, topo):
+    pwp = PwPolicyManager(topo.standalone)
+    orl = pwp.get_pwpolicy_entry(f'uid=orla,ou=dirsec,{DEFAULT_SUFFIX}')
+    joe = pwp.get_pwpolicy_entry(f'uid=joe,ou=people,{DEFAULT_SUFFIX}')
+    people = pwp.get_pwpolicy_entry(f'ou=people,{DEFAULT_SUFFIX}')
+    change_password_with_admin(topo, [
+        ('uid=orla,ou=dirsec', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p1')
+    ])
+    for pwp1 in [orl, joe, people]:
+        assert pwp1.get_attr_val_utf8('passwordminage') == '0'
+        pwp1.replace_many(
+            ('passwordminage', '10'),
+            ('passwordChange', 'on'))
+
+    def final_step():
+        for pwp2 in [orl, joe, people]:
+            pwp2.replace('passwordminage', '0')
+    request.addfinalizer(final_step)
+
+
+def test_password_minimum_age_section(topo, _policy_setup, _fixture_for_password_min_age):
+    """ Password History Section.
+
+        :id: 470f5b2a-a0ba-11ea-ab2d-8c16451d917b
+        :setup: Standalone
+        :steps:
+            1. Searching for password minimum age, should be 0 per defaults set
+            2. Change current password from *1 to *2
+            3. Wait 5 secs and try to change again.  Should fail.
+            4. Wait more time to complete password min age
+            5. Now user can change password
+        :expected results:
+            1. Success
+            2. Success
+            3. Fail
+            4. Success
+            5. Success
+    """
+    # Change current password from *1 to *2
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb1', '000rLb2'),
+        ('uid=joe,ou=people', '00J0e1', '00J0e2'),
+        ('uid=jack,ou=people', '00J6ck1', '00J6ck2'),
+        ('uid=deep,ou=others,ou=people', '00De3p1', '00De3p2')
+    ])
+    # Wait 5 secs and try to change again.  Should fail.
+    count = 0
+    while count < 8:
+        with pytest.raises(ldap.CONSTRAINT_VIOLATION):
+            change_password(topo, [
+                ('uid=orla,ou=dirsec', '000rLb2', '000rLb1'),
+                ('uid=joe,ou=people', '00J0e2', '00J0e1'),
+                ('uid=jack,ou=people', '00J6ck2', '00J6ck1'),
+                ('uid=deep,ou=others,ou=people', '00De3p2', '00De3p1')
+            ])
+        time.sleep(1)
+        count += 1
+    # Wait more time to complete password min age
+    for _ in range(3):
+        time.sleep(1)
+    # Now user can change password
+    change_password(topo, [
+        ('uid=orla,ou=dirsec', '000rLb2', '000rLb1'),
+        ('uid=joe,ou=people', '00J0e2', '00J0e1'),
+        ('uid=jack,ou=people', '00J6ck2', '00J6ck1'),
+        ('uid=deep,ou=others,ou=people', '00De3p2', '00De3p1')
+    ])
+
+
 if __name__ == "__main__":
     CURRENT_FILE = os.path.realpath(__file__)
     pytest.main("-s -v %s" % CURRENT_FILE)
\ No newline at end of file

