| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- # --- BEGIN COPYRIGHT BLOCK ---
- # Copyright (C) 2016 Red Hat, Inc.
- # All rights reserved.
- #
- # License: GPL (version 3 or any later version).
- # See LICENSE for details.
- # --- END COPYRIGHT BLOCK ---
- #
- import pytest
- from lib389.tasks import *
- from lib389.utils import *
- from lib389.topologies import topology_st
- OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
- TEST_USER_NAME = 'simplepaged_test'
- TEST_USER_DN = 'uid={},{}'.format(TEST_USER_NAME, OU_PEOPLE)
- TEST_USER_PWD = 'simplepaged_test'
- PW_POLICY_CONT_USER = 'cn="cn=nsPwPolicyEntry,uid=simplepaged_test,' \
- 'ou=people,dc=example,dc=com",' \
- 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
- PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,' \
- 'ou=people,dc=example,dc=com",' \
- 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
- logging.getLogger(__name__).setLevel(logging.INFO)
- log = logging.getLogger(__name__)
- @pytest.fixture(scope="module")
- def test_user(topology_st, request):
- """User for binding operation"""
- log.info('Adding user {}'.format(TEST_USER_DN))
- try:
- topology_st.standalone.add_s(Entry((TEST_USER_DN, {
- 'objectclass': 'top person'.split(),
- 'objectclass': 'organizationalPerson',
- 'objectclass': 'inetorgperson',
- 'cn': TEST_USER_NAME,
- 'sn': TEST_USER_NAME,
- 'userpassword': TEST_USER_PWD,
- 'mail': '%[email protected]' % TEST_USER_NAME,
- 'uid': TEST_USER_NAME
- })))
- except ldap.LDAPError as e:
- log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
- e.message['desc']))
- raise e
- def fin():
- log.info('Deleting user {}'.format(TEST_USER_DN))
- topology_st.standalone.delete_s(TEST_USER_DN)
- request.addfinalizer(fin)
- @pytest.fixture(scope="module")
- def password_policy(topology_st, test_user):
- """Set up password policy for subtree and user"""
- log.info('Enable fine-grained policy')
- try:
- topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
- 'nsslapd-pwpolicy-local',
- 'on')])
- except ldap.LDAPError as e:
- log.error('Failed to set fine-grained policy: error {}'.format(
- e.message['desc']))
- raise e
- log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
- try:
- subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(),
- '-D', DN_DM, '-w', PASSWORD,
- '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
- '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE])
- except subprocess.CalledProcessError as e:
- log.error('Failed to create pw policy policy for {}: error {}'.format(
- OU_PEOPLE, e.message['desc']))
- raise e
- log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
- try:
- topology_st.standalone.modify_s(OU_PEOPLE, [(ldap.MOD_REPLACE,
- 'pwdpolicysubentry',
- PW_POLICY_CONT_PEOPLE)])
- except ldap.LDAPError as e:
- log.error('Failed to pwdpolicysubentry pw policy ' \
- 'policy for {}: error {}'.format(OU_PEOPLE,
- e.message['desc']))
- raise e
- log.info('Create password policy for subtree {}'.format(TEST_USER_DN))
- try:
- subprocess.call(['%s/ns-newpwpolicy.pl' % topology_st.standalone.get_sbin_dir(),
- '-D', DN_DM, '-w', PASSWORD,
- '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
- '-U', TEST_USER_DN, '-Z', SERVERID_STANDALONE])
- except subprocess.CalledProcessError as e:
- log.error('Failed to create pw policy policy for {}: error {}'.format(
- TEST_USER_DN, e.message['desc']))
- raise e
- log.info('Add pwdpolicysubentry attribute to {}'.format(TEST_USER_DN))
- try:
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'pwdpolicysubentry',
- PW_POLICY_CONT_USER)])
- except ldap.LDAPError as e:
- log.error('Failed to pwdpolicysubentry pw policy ' \
- 'policy for {}: error {}'.format(TEST_USER_DN,
- e.message['desc']))
- raise e
- @pytest.mark.parametrize('subtree_pwchange,user_pwchange,exception',
- [('on', 'off', ldap.UNWILLING_TO_PERFORM),
- ('off', 'off', ldap.UNWILLING_TO_PERFORM),
- ('off', 'on', None), ('on', 'on', None)])
- def test_change_pwd(topology_st, test_user, password_policy,
- subtree_pwchange, user_pwchange, exception):
- """Verify that 'passwordChange' attr works as expected
- User should have a priority over a subtree.
- :Feature: Password policy
- :Setup: Standalone instance, test user,
- password policy entries for a user and a subtree
- :Steps: 1. Set passwordChange on the user and the subtree
- to various combinations
- 2. Bind as test user
- 3. Try to change password
- :Assert: Subtree/User passwordChange - result
- off/on, on/on - success
- on/off, off/off - UNWILLING_TO_PERFORM
- """
- log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange,
- PW_POLICY_CONT_PEOPLE))
- try:
- topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
- 'passwordChange',
- subtree_pwchange)])
- except ldap.LDAPError as e:
- log.error('Failed to set passwordChange ' \
- 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
- e.message['desc']))
- raise e
- log.info('Set passwordChange to "{}" - {}'.format(user_pwchange,
- PW_POLICY_CONT_USER))
- try:
- topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
- 'passwordChange',
- user_pwchange)])
- except ldap.LDAPError as e:
- log.error('Failed to set passwordChange ' \
- 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
- e.message['desc']))
- raise e
- time.sleep(1)
- try:
- log.info('Bind as user and modify userPassword')
- topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
- if exception:
- with pytest.raises(exception):
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- 'new_pass')])
- else:
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- 'new_pass')])
- except ldap.LDAPError as e:
- log.error('Failed to change userpassword for {}: error {}'.format(
- TEST_USER_DN, e.message['info']))
- raise e
- finally:
- log.info('Bind as DM')
- topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- TEST_USER_PWD)])
- def test_pwd_min_age(topology_st, test_user, password_policy):
- """If we set passwordMinAge to some value, for example to 10, then it
- should not allow the user to change the password within 10 seconds after
- his previous change.
- :Feature: Password policy
- :Setup: Standalone instance, test user,
- password policy entries for a user and a subtree
- :Steps: 1. Set passwordMinAge to 10 on the user pwpolicy entry
- 2. Set passwordMinAge to 10 on the subtree pwpolicy entry
- 3. Set passwordMinAge to 10 on the cn=config entry
- 4. Bind as test user
- 5. Try to change password two times in a row
- 6. Wait 12 seconds
- 7. Try to change password
- :Assert: User should be not allowed to change the password
- right after previous change - CONSTRAINT_VIOLATION
- User should be not allowed to change the password
- after 12 seconds passed
- """
- num_seconds = '10'
- log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_PEOPLE))
- try:
- topology_st.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
- 'passwordminage',
- num_seconds)])
- except ldap.LDAPError as e:
- log.error('Failed to set passwordminage ' \
- 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
- e.message['desc']))
- raise e
- log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_USER))
- try:
- topology_st.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
- 'passwordminage',
- num_seconds)])
- except ldap.LDAPError as e:
- log.error('Failed to set passwordminage ' \
- 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
- e.message['desc']))
- raise e
- log.info('Set passwordminage to "{}" - {}'.format(num_seconds, DN_CONFIG))
- try:
- topology_st.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
- 'passwordminage',
- num_seconds)])
- except ldap.LDAPError as e:
- log.error('Failed to set passwordminage ' \
- 'policy for {}: error {}'.format(DN_CONFIG,
- e.message['desc']))
- raise e
- time.sleep(1)
- try:
- log.info('Bind as user and modify userPassword')
- topology_st.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- 'new_pass')])
- except ldap.LDAPError as e:
- log.error('Failed to change userpassword for {}: error {}'.format(
- TEST_USER_DN, e.message['info']))
- raise e
- time.sleep(1)
- log.info('Bind as user and modify userPassword straight away after previous change')
- topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
- with pytest.raises(ldap.CONSTRAINT_VIOLATION):
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- 'new_new_pass')])
- log.info('Wait {} second'.format(int(num_seconds) + 2))
- time.sleep(int(num_seconds) + 2)
- try:
- log.info('Bind as user and modify userPassword')
- topology_st.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- TEST_USER_PWD)])
- except ldap.LDAPError as e:
- log.error('Failed to change userpassword for {}: error {}'.format(
- TEST_USER_DN, e.message['info']))
- raise e
- finally:
- log.info('Bind as DM')
- topology_st.standalone.simple_bind_s(DN_DM, PASSWORD)
- topology_st.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
- 'userPassword',
- TEST_USER_PWD)])
- if __name__ == '__main__':
- # Run isolated
- # -s for DEBUG mode
- CURRENT_FILE = os.path.realpath(__file__)
- pytest.main("-s %s" % CURRENT_FILE)
|