From d49f1bb5896e67935b4cbd9728ded8d7cff1cb23 Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Tue, 19 Jan 2016 13:48:57 -0800 Subject: [PATCH] Ticket #548 - CI test: added test cases for ticket 548 Description: RFE: Allow AD password sync to update shadowLastChange 1) Use DEFAULT_SUFFIX_ESCAPED for the escaped DEFAULT_SUFFIX. 2) Check USER1's shadow values are adjusted by changing the password policy. First, the default values. Next, Global password policy then fine-grained password policy is added. 3) Checks changes to the global pw policy are reflected on pw change 3) Checks changes to the subtree pw policy are reflected on pw change Author: nhosoi, wibrown Review: ??? --- dirsrvtests/tickets/ticket548_test.py | 131 ++++++++++++++++++++++++++++------ 1 file changed, 108 insertions(+), 23 deletions(-) diff --git a/dirsrvtests/tickets/ticket548_test.py b/dirsrvtests/tickets/ticket548_test.py index 030ff4f..d29fa53 100644 --- a/dirsrvtests/tickets/ticket548_test.py +++ b/dirsrvtests/tickets/ticket548_test.py @@ -26,9 +26,9 @@ installation_prefix = None # Assuming DEFAULT_SUFFIX is "dc=example,dc=com", otherwise it does not work... :( SUBTREE_CONTAINER = 'cn=nsPwPolicyContainer,' + DEFAULT_SUFFIX SUBTREE_PWPDN = 'cn=nsPwPolicyEntry,' + DEFAULT_SUFFIX -SUBTREE_PWP = 'cn=cn\3DnsPwPolicyEntry\2Cdc\3Dexample\2Cdc\3Dcom,' + SUBTREE_CONTAINER +SUBTREE_PWP = 'cn=cn\3DnsPwPolicyEntry\2C' + DEFAULT_SUFFIX_ESCAPED + ',' + SUBTREE_CONTAINER SUBTREE_COS_TMPLDN = 'cn=nsPwTemplateEntry,' + DEFAULT_SUFFIX -SUBTREE_COS_TMPL = 'cn=cn\3DnsPwTemplateEntry\2Cdc\3Dexample\2Cdc\3Dcom,' + SUBTREE_CONTAINER +SUBTREE_COS_TMPL = 'cn=cn\3DnsPwTemplateEntry\2C' + DEFAULT_SUFFIX_ESCAPED + ',' + SUBTREE_CONTAINER SUBTREE_COS_DEF = 'cn=nsPwPolicy_CoS,' + DEFAULT_SUFFIX USER1_DN = 'uid=user1,' + DEFAULT_SUFFIX @@ -72,8 +72,12 @@ def topology(request): return TopologyStandalone(standalone) +def days_to_secs(days): + # Value of 60 * 60 * 24 + return days * 86400 -def set_global_pwpolicy(topology): +# Values are in days +def set_global_pwpolicy(topology, min_=1, max_=10, warn=3): log.info(" +++++ Enable global password policy +++++\n") # Enable password policy try: @@ -82,47 +86,64 @@ def set_global_pwpolicy(topology): log.error('Failed to set pwpolicy-local: error ' + e.message['desc']) assert False - log.info(" Set global password Min Age -- 1 day\n") + # Convert our values to seconds + min_secs = days_to_secs(min_) + max_secs = days_to_secs(max_) + warn_secs = days_to_secs(warn) + + log.info(" Set global password Min Age -- %s day\n"% min_) try: - topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMinAge', '86400')]) + topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMinAge', '%s' % min_secs)]) except ldap.LDAPError as e: log.error('Failed to set passwordMinAge: error ' + e.message['desc']) assert False - log.info(" Set global password Max Age -- 10 days\n") + log.info(" Set global password Max Age -- %s days\n" % max_) try: - topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMaxAge', '864000')]) + topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordMaxAge', '%s' % max_secs)]) except ldap.LDAPError as e: log.error('Failed to set passwordMaxAge: error ' + e.message['desc']) assert False - log.info(" Set global password Warning -- 3 days\n") + log.info(" Set global password Warning -- %s days\n" % warn) try: - topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordWarning', '259200')]) + topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE, 'passwordWarning', '%s' % warn_secs)]) except ldap.LDAPError as e: log.error('Failed to set passwordWarning: error ' + e.message['desc']) assert False -def set_subtree_pwpolicy(topology): +def set_subtree_pwpolicy(topology, min_=2, max_=20, warn=6): log.info(" +++++ Enable subtree level password policy +++++\n") + + # Convert our values to seconds + min_secs = days_to_secs(min_) + max_secs = days_to_secs(max_) + warn_secs = days_to_secs(warn) + log.info(" Add the container") try: topology.standalone.add_s(Entry((SUBTREE_CONTAINER, {'objectclass': 'top nsContainer'.split(), 'cn': 'nsPwPolicyContainer'}))) except ldap.LDAPError as e: log.error('Failed to add subtree container: error ' + e.message['desc']) - assert False + #assert False - log.info(" Add the password policy subentry {passwordMustChange: on, passwordMinAge: 2, passwordMaxAge: 20, passwordWarning: 6}") + try: + # Purge the old policy + topology.standalone.delete_s(SUBTREE_PWP) + except: + pass + + log.info(" Add the password policy subentry {passwordMustChange: on, passwordMinAge: %s, passwordMaxAge: %s, passwordWarning: %s}" % (min_, max_, warn)) try: topology.standalone.add_s(Entry((SUBTREE_PWP, {'objectclass': 'top ldapsubentry passwordpolicy'.split(), 'cn': SUBTREE_PWPDN, 'passwordMustChange': 'on', 'passwordExp': 'on', - 'passwordMinAge': '172800', - 'passwordMaxAge': '1728000', - 'passwordWarning': '518400', + 'passwordMinAge': '%s' % min_secs, + 'passwordMaxAge': '%s' % max_secs, + 'passwordWarning': '%s' % warn_secs, 'passwordChange': 'on', 'passwordStorageScheme': 'clear'}))) except ldap.LDAPError as e: @@ -138,7 +159,7 @@ def set_subtree_pwpolicy(topology): 'pwdpolicysubentry': SUBTREE_PWP}))) except ldap.LDAPError as e: log.error('Failed to add COS template: error ' + e.message['desc']) - assert False + #assert False log.info(" Add the COS definition") try: @@ -148,11 +169,10 @@ def set_subtree_pwpolicy(topology): 'cosAttribute': 'pwdpolicysubentry default operational-default'}))) except ldap.LDAPError as e: log.error('Failed to add COS def: error ' + e.message['desc']) - assert False + #assert False time.sleep(1) - def update_passwd(topology, user, passwd, newpasswd): log.info(" Bind as {%s,%s}" % (user, passwd)) topology.standalone.simple_bind_s(user, passwd) @@ -195,7 +215,7 @@ def test_ticket548_test_with_no_policy(topology): 'cn': 'user 1', 'uid': 'user1', 'givenname': 'user', - 'mail': 'user1@example.com', + 'mail': 'user1@' + DEFAULT_SUFFIX, 'userpassword': USER_PW}))) except ldap.LDAPError as e: log.fatal('test_ticket548: Failed to add user' + USER1_DN + ': error ' + e.message['desc']) @@ -231,16 +251,33 @@ def test_ticket548_test_global_policy(topology): 'cn': 'user 2', 'uid': 'user2', 'givenname': 'user', - 'mail': 'user2@example.com', + 'mail': 'user2@' + DEFAULT_SUFFIX, 'userpassword': USER_PW}))) except ldap.LDAPError as e: log.fatal('test_ticket548: Failed to add user' + USER2_DN + ': error ' + e.message['desc']) assert False + edate = int(time.time() / (60 * 60 * 24)) + + log.info("Bind as %s" % USER1_DN) + topology.standalone.simple_bind_s(USER1_DN, USER_PW) + + log.info('Search entry %s' % USER1_DN) + entry = topology.standalone.getEntry(USER1_DN, ldap.SCOPE_BASE, "(objectclass=*)") + check_shadow_attr_value(entry, 'shadowLastChange', edate, USER1_DN) + + # passwordMinAge -- 1 day + check_shadow_attr_value(entry, 'shadowMin', 1, USER1_DN) + + # passwordMaxAge -- 10 days + check_shadow_attr_value(entry, 'shadowMax', 10, USER1_DN) + + # passwordWarning -- 3 days + check_shadow_attr_value(entry, 'shadowWarning', 3, USER1_DN) + log.info("Bind as %s" % USER2_DN) topology.standalone.simple_bind_s(USER2_DN, USER_PW) - edate = int(time.time() / (60 * 60 * 24)) log.info('Search entry %s' % USER2_DN) entry = topology.standalone.getEntry(USER2_DN, ldap.SCOPE_BASE, "(objectclass=*)") check_shadow_attr_value(entry, 'shadowLastChange', edate, USER2_DN) @@ -254,6 +291,34 @@ def test_ticket548_test_global_policy(topology): # passwordWarning -- 3 days check_shadow_attr_value(entry, 'shadowWarning', 3, USER2_DN) + # Bind as DM again, change policy + log.info("Bind as %s" % DN_DM) + topology.standalone.simple_bind_s(DN_DM, PASSWORD) + set_global_pwpolicy(topology, 3, 30, 9) + + # change the user password, then check again. + log.info("Bind as %s" % USER2_DN) + topology.standalone.simple_bind_s(USER2_DN, USER_PW) + + newpasswd = USER_PW + '2' + update_passwd(topology, USER2_DN, USER_PW, newpasswd) + + log.info("Re-bind as %s with new password" % USER2_DN) + topology.standalone.simple_bind_s(USER2_DN, newpasswd) + + ## This tests if we update the shadow values on password change. + log.info('Search entry %s' % USER2_DN) + entry = topology.standalone.getEntry(USER2_DN, ldap.SCOPE_BASE, "(objectclass=*)") + + # passwordMinAge -- 1 day + check_shadow_attr_value(entry, 'shadowMin', 3, USER2_DN) + + # passwordMaxAge -- 10 days + check_shadow_attr_value(entry, 'shadowMax', 30, USER2_DN) + + # passwordWarning -- 3 days + check_shadow_attr_value(entry, 'shadowWarning', 9, USER2_DN) + log.info("Check shadowAccount with global policy was successfully verified.") @@ -266,8 +331,9 @@ def test_ticket548_test_subtree_policy(topology): log.info("Bind as %s" % DN_DM) topology.standalone.simple_bind_s(DN_DM, PASSWORD) + # Check the global policy values - set_subtree_pwpolicy(topology) + set_subtree_pwpolicy(topology, 2, 20, 6) log.info('Add an entry' + USER3_DN) try: @@ -276,7 +342,7 @@ def test_ticket548_test_subtree_policy(topology): 'cn': 'user 3', 'uid': 'user3', 'givenname': 'user', - 'mail': 'user3@example.com', + 'mail': 'user3@' + DEFAULT_SUFFIX, 'userpassword': USER_PW}))) except ldap.LDAPError as e: log.fatal('test_ticket548: Failed to add user' + USER3_DN + ': error ' + e.message['desc']) @@ -312,6 +378,12 @@ def test_ticket548_test_subtree_policy(topology): log.info("Bind as %s and updating the password with a new one" % USER3_DN) topology.standalone.simple_bind_s(USER3_DN, USER_PW) + # Bind as DM again, change policy + log.info("Bind as %s" % DN_DM) + topology.standalone.simple_bind_s(DN_DM, PASSWORD) + + set_subtree_pwpolicy(topology, 4, 40, 12) + newpasswd = USER_PW + '0' update_passwd(topology, USER3_DN, USER_PW, newpasswd) @@ -329,6 +401,19 @@ def test_ticket548_test_subtree_policy(topology): log.info('Expecting shadowLastChange %d once userPassword is updated', edate) check_shadow_attr_value(entry2, 'shadowLastChange', edate, USER3_DN) + log.info('Search entry %s' % USER3_DN) + entry = topology.standalone.getEntry(USER3_DN, ldap.SCOPE_BASE, "(objectclass=*)") + check_shadow_attr_value(entry, 'shadowLastChange', edate, USER3_DN) + + # passwordMinAge -- 1 day + check_shadow_attr_value(entry, 'shadowMin', 4, USER3_DN) + + # passwordMaxAge -- 10 days + check_shadow_attr_value(entry, 'shadowMax', 40, USER3_DN) + + # passwordWarning -- 3 days + check_shadow_attr_value(entry, 'shadowWarning', 12, USER3_DN) + log.info("Check shadowAccount with subtree level policy was successfully verified.") -- 2.5.0