|
|
7c7f29 |
From 986930d491d64ce32b91ed70d452074f2963fc55 Mon Sep 17 00:00:00 2001
|
|
|
7c7f29 |
From: Simon Pichugin <spichugi@redhat.com>
|
|
|
7c7f29 |
Date: Wed, 24 Aug 2016 10:08:29 +0200
|
|
|
7c7f29 |
Subject: [PATCH 42/45] Ticket 48967 - Add CI test and refactor test suite
|
|
|
7c7f29 |
|
|
|
7c7f29 |
Description: Add a test case to password policy test suite.
|
|
|
7c7f29 |
Refactor structure of password test suite so it would become more
|
|
|
7c7f29 |
logical.
|
|
|
7c7f29 |
|
|
|
7c7f29 |
https://fedorahosted.org/389/ticket/48967
|
|
|
7c7f29 |
|
|
|
7c7f29 |
Reviewed by: nhosoi (Thank you, Noriko!)
|
|
|
7c7f29 |
|
|
|
7c7f29 |
(cherry picked from commit 6abd5f49d8e32732a97794e68f642045f16f23e3)
|
|
|
7c7f29 |
---
|
|
|
7c7f29 |
.../suites/password/pwdPolicy_attribute_test.py | 339 +++++++++++++++++++++
|
|
|
7c7f29 |
.../tests/suites/password/pwdPolicy_syntax_test.py | 151 +++++++++
|
|
|
7c7f29 |
.../tests/suites/password/pwdPolicy_test.py | 151 ---------
|
|
|
7c7f29 |
.../tests/suites/password/pwd_change_policytest.py | 240 ---------------
|
|
|
7c7f29 |
4 files changed, 490 insertions(+), 391 deletions(-)
|
|
|
7c7f29 |
create mode 100644 dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
7c7f29 |
create mode 100644 dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
|
|
|
7c7f29 |
delete mode 100644 dirsrvtests/tests/suites/password/pwdPolicy_test.py
|
|
|
7c7f29 |
delete mode 100644 dirsrvtests/tests/suites/password/pwd_change_policytest.py
|
|
|
7c7f29 |
|
|
|
7c7f29 |
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
7c7f29 |
new file mode 100644
|
|
|
7c7f29 |
index 0000000..d3be7e2
|
|
|
7c7f29 |
--- /dev/null
|
|
|
7c7f29 |
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_attribute_test.py
|
|
|
7c7f29 |
@@ -0,0 +1,339 @@
|
|
|
7c7f29 |
+import os
|
|
|
7c7f29 |
+import sys
|
|
|
7c7f29 |
+import time
|
|
|
7c7f29 |
+import subprocess
|
|
|
7c7f29 |
+import ldap
|
|
|
7c7f29 |
+import logging
|
|
|
7c7f29 |
+import pytest
|
|
|
7c7f29 |
+from lib389 import DirSrv, Entry, tools, tasks
|
|
|
7c7f29 |
+from lib389.tools import DirSrvTools
|
|
|
7c7f29 |
+from lib389._constants import *
|
|
|
7c7f29 |
+from lib389.properties import *
|
|
|
7c7f29 |
+from lib389.tasks import *
|
|
|
7c7f29 |
+from lib389.utils import *
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+DEBUGGING = False
|
|
|
7c7f29 |
+OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
|
|
|
7c7f29 |
+TEST_USER_NAME = 'simplepaged_test'
|
|
|
7c7f29 |
+TEST_USER_DN = 'uid={},{}'.format(TEST_USER_NAME, OU_PEOPLE)
|
|
|
7c7f29 |
+TEST_USER_PWD = 'simplepaged_test'
|
|
|
7c7f29 |
+PW_POLICY_CONT_USER = 'cn="cn=nsPwPolicyEntry,uid=simplepaged_test,'\
|
|
|
7c7f29 |
+ 'ou=people,dc=example,dc=com",'\
|
|
|
7c7f29 |
+ 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
|
|
|
7c7f29 |
+PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,'\
|
|
|
7c7f29 |
+ 'ou=people,dc=example,dc=com",'\
|
|
|
7c7f29 |
+ 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+if DEBUGGING:
|
|
|
7c7f29 |
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
+else:
|
|
|
7c7f29 |
+ logging.getLogger(__name__).setLevel(logging.INFO)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+log = logging.getLogger(__name__)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+class TopologyStandalone(object):
|
|
|
7c7f29 |
+ """The DS Topology Class"""
|
|
|
7c7f29 |
+ def __init__(self, standalone):
|
|
|
7c7f29 |
+ """Init"""
|
|
|
7c7f29 |
+ standalone.open()
|
|
|
7c7f29 |
+ self.standalone = standalone
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+@pytest.fixture(scope="module")
|
|
|
7c7f29 |
+def topology(request):
|
|
|
7c7f29 |
+ """Create DS Deployment"""
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Creating standalone instance ...
|
|
|
7c7f29 |
+ if DEBUGGING:
|
|
|
7c7f29 |
+ standalone = DirSrv(verbose=True)
|
|
|
7c7f29 |
+ else:
|
|
|
7c7f29 |
+ standalone = DirSrv(verbose=False)
|
|
|
7c7f29 |
+ args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
7c7f29 |
+ args_standalone = args_instance.copy()
|
|
|
7c7f29 |
+ standalone.allocate(args_standalone)
|
|
|
7c7f29 |
+ instance_standalone = standalone.exists()
|
|
|
7c7f29 |
+ if instance_standalone:
|
|
|
7c7f29 |
+ standalone.delete()
|
|
|
7c7f29 |
+ standalone.create()
|
|
|
7c7f29 |
+ standalone.open()
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ def fin():
|
|
|
7c7f29 |
+ """If we are debugging just stop the instances, otherwise remove
|
|
|
7c7f29 |
+ them
|
|
|
7c7f29 |
+ """
|
|
|
7c7f29 |
+ if DEBUGGING:
|
|
|
7c7f29 |
+ standalone.stop()
|
|
|
7c7f29 |
+ else:
|
|
|
7c7f29 |
+ standalone.delete()
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ request.addfinalizer(fin)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ return TopologyStandalone(standalone)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+@pytest.fixture(scope="module")
|
|
|
7c7f29 |
+def test_user(topology, request):
|
|
|
7c7f29 |
+ """User for binding operation"""
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Adding user {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.add_s(Entry((TEST_USER_DN, {
|
|
|
7c7f29 |
+ 'objectclass': 'top person'.split(),
|
|
|
7c7f29 |
+ 'objectclass': 'organizationalPerson',
|
|
|
7c7f29 |
+ 'objectclass': 'inetorgperson',
|
|
|
7c7f29 |
+ 'cn': TEST_USER_NAME,
|
|
|
7c7f29 |
+ 'sn': TEST_USER_NAME,
|
|
|
7c7f29 |
+ 'userpassword': TEST_USER_PWD,
|
|
|
7c7f29 |
+ 'mail': '%s@redhat.com' % TEST_USER_NAME,
|
|
|
7c7f29 |
+ 'uid': TEST_USER_NAME
|
|
|
7c7f29 |
+ })))
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ def fin():
|
|
|
7c7f29 |
+ log.info('Deleting user {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
+ topology.standalone.delete_s(TEST_USER_DN)
|
|
|
7c7f29 |
+ request.addfinalizer(fin)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+@pytest.fixture(scope="module")
|
|
|
7c7f29 |
+def password_policy(topology, test_user):
|
|
|
7c7f29 |
+ """Set up password policy for subtree and user"""
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Enable fine-grained policy')
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'nsslapd-pwpolicy-local',
|
|
|
7c7f29 |
+ 'on')])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set fine-grained policy: error {}'.format(
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ subprocess.call(['ns-newpwpolicy.pl', '-D', DN_DM, '-w', PASSWORD,
|
|
|
7c7f29 |
+ '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
|
|
|
7c7f29 |
+ '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE])
|
|
|
7c7f29 |
+ except subprocess.CalledProcessError as e:
|
|
|
7c7f29 |
+ log.error('Failed to create pw policy policy for {}: error {}'.format(
|
|
|
7c7f29 |
+ OU_PEOPLE, e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(OU_PEOPLE, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'pwdpolicysubentry',
|
|
|
7c7f29 |
+ PW_POLICY_CONT_PEOPLE)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to pwdpolicysubentry pw policy '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(OU_PEOPLE,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Create password policy for subtree {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ subprocess.call(['ns-newpwpolicy.pl', '-D', DN_DM, '-w', PASSWORD,
|
|
|
7c7f29 |
+ '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
|
|
|
7c7f29 |
+ '-U', TEST_USER_DN, '-Z', SERVERID_STANDALONE])
|
|
|
7c7f29 |
+ except subprocess.CalledProcessError as e:
|
|
|
7c7f29 |
+ log.error('Failed to create pw policy policy for {}: error {}'.format(
|
|
|
7c7f29 |
+ TEST_USER_DN, e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Add pwdpolicysubentry attribute to {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'pwdpolicysubentry',
|
|
|
7c7f29 |
+ PW_POLICY_CONT_USER)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to pwdpolicysubentry pw policy '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(TEST_USER_DN,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+@pytest.mark.parametrize('subtree_pwchange,user_pwchange,exception',
|
|
|
7c7f29 |
+ [('on', 'off', ldap.UNWILLING_TO_PERFORM),
|
|
|
7c7f29 |
+ ('off', 'off', ldap.UNWILLING_TO_PERFORM),
|
|
|
7c7f29 |
+ ('off', 'on', None), ('on', 'on', None)])
|
|
|
7c7f29 |
+def test_change_pwd(topology, test_user, password_policy,
|
|
|
7c7f29 |
+ subtree_pwchange, user_pwchange, exception):
|
|
|
7c7f29 |
+ """Verify that 'passwordChange' attr works as expected
|
|
|
7c7f29 |
+ User should have a priority over a subtree.
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Feature: Password policy
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Setup: Standalone instance, test user,
|
|
|
7c7f29 |
+ password policy entries for a user and a subtree
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Steps: 1. Set passwordChange on the user and the subtree
|
|
|
7c7f29 |
+ to various combinations
|
|
|
7c7f29 |
+ 2. Bind as test user
|
|
|
7c7f29 |
+ 3. Try to change password
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Assert: Subtree/User passwordChange - result
|
|
|
7c7f29 |
+ off/on, on/on - success
|
|
|
7c7f29 |
+ on/off, off/off - UNWILLING_TO_PERFORM
|
|
|
7c7f29 |
+ """
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange,
|
|
|
7c7f29 |
+ PW_POLICY_CONT_PEOPLE))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'passwordChange',
|
|
|
7c7f29 |
+ subtree_pwchange)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set passwordChange '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Set passwordChange to "{}" - {}'.format(user_pwchange,
|
|
|
7c7f29 |
+ PW_POLICY_CONT_USER))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'passwordChange',
|
|
|
7c7f29 |
+ user_pwchange)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set passwordChange '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ log.info('Bind as user and modify userPassword')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
|
|
7c7f29 |
+ if exception:
|
|
|
7c7f29 |
+ with pytest.raises(exception):
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ 'new_pass')])
|
|
|
7c7f29 |
+ else:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ 'new_pass')])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to change userpassword for {}: error {}'.format(
|
|
|
7c7f29 |
+ TEST_USER_DN, e.message['info']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+ finally:
|
|
|
7c7f29 |
+ log.info('Bind as DM')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ TEST_USER_PWD)])
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+def test_pwd_min_age(topology, test_user, password_policy):
|
|
|
7c7f29 |
+ """If we set passwordMinAge to some value, for example to 10, then it
|
|
|
7c7f29 |
+ should not allow the user to change the password within 10 seconds after
|
|
|
7c7f29 |
+ his previous change.
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Feature: Password policy
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Setup: Standalone instance, test user,
|
|
|
7c7f29 |
+ password policy entries for a user and a subtree
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Steps: 1. Set passwordMinAge to 10 on the user pwpolicy entry
|
|
|
7c7f29 |
+ 2. Set passwordMinAge to 10 on the subtree pwpolicy entry
|
|
|
7c7f29 |
+ 3. Set passwordMinAge to 10 on the cn=config entry
|
|
|
7c7f29 |
+ 4. Bind as test user
|
|
|
7c7f29 |
+ 5. Try to change password two times in a row
|
|
|
7c7f29 |
+ 6. Wait 12 seconds
|
|
|
7c7f29 |
+ 7. Try to change password
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ :Assert: User should be not allowed to change the password
|
|
|
7c7f29 |
+ right after previous change - CONSTRAINT_VIOLATION
|
|
|
7c7f29 |
+ User should be not allowed to change the password
|
|
|
7c7f29 |
+ after 12 seconds passed
|
|
|
7c7f29 |
+ """
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ num_seconds = '10'
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_PEOPLE))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'passwordminage',
|
|
|
7c7f29 |
+ num_seconds)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set passwordminage '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Set passwordminage to "{}" - {}'.format(num_seconds, PW_POLICY_CONT_USER))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'passwordminage',
|
|
|
7c7f29 |
+ num_seconds)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set passwordminage '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Set passwordminage to "{}" - {}'.format(num_seconds, DN_CONFIG))
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'passwordminage',
|
|
|
7c7f29 |
+ num_seconds)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to set passwordminage '\
|
|
|
7c7f29 |
+ 'policy for {}: error {}'.format(DN_CONFIG,
|
|
|
7c7f29 |
+ e.message['desc']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ log.info('Bind as user and modify userPassword')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ 'new_pass')])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to change userpassword for {}: error {}'.format(
|
|
|
7c7f29 |
+ TEST_USER_DN, e.message['info']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Bind as user and modify userPassword straight away after previous change')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
|
|
|
7c7f29 |
+ with pytest.raises(ldap.CONSTRAINT_VIOLATION):
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ 'new_new_pass')])
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ log.info('Wait {} second'.format(int(num_seconds) + 2))
|
|
|
7c7f29 |
+ time.sleep(int(num_seconds) + 2)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ log.info('Bind as user and modify userPassword')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(TEST_USER_DN, 'new_pass')
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ TEST_USER_PWD)])
|
|
|
7c7f29 |
+ except ldap.LDAPError as e:
|
|
|
7c7f29 |
+ log.error('Failed to change userpassword for {}: error {}'.format(
|
|
|
7c7f29 |
+ TEST_USER_DN, e.message['info']))
|
|
|
7c7f29 |
+ raise e
|
|
|
7c7f29 |
+ finally:
|
|
|
7c7f29 |
+ log.info('Bind as DM')
|
|
|
7c7f29 |
+ topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
7c7f29 |
+ topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
+ 'userPassword',
|
|
|
7c7f29 |
+ TEST_USER_PWD)])
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+if __name__ == '__main__':
|
|
|
7c7f29 |
+ # Run isolated
|
|
|
7c7f29 |
+ # -s for DEBUG mode
|
|
|
7c7f29 |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
7c7f29 |
+ pytest.main("-s %s" % CURRENT_FILE)
|
|
|
7c7f29 |
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
|
|
|
7c7f29 |
new file mode 100644
|
|
|
7c7f29 |
index 0000000..653d033
|
|
|
7c7f29 |
--- /dev/null
|
|
|
7c7f29 |
+++ b/dirsrvtests/tests/suites/password/pwdPolicy_syntax_test.py
|
|
|
7c7f29 |
@@ -0,0 +1,151 @@
|
|
|
7c7f29 |
+# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
7c7f29 |
+# Copyright (C) 2015 Red Hat, Inc.
|
|
|
7c7f29 |
+# All rights reserved.
|
|
|
7c7f29 |
+#
|
|
|
7c7f29 |
+# License: GPL (version 3 or any later version).
|
|
|
7c7f29 |
+# See LICENSE for details.
|
|
|
7c7f29 |
+# --- END COPYRIGHT BLOCK ---
|
|
|
7c7f29 |
+#
|
|
|
7c7f29 |
+import os
|
|
|
7c7f29 |
+import sys
|
|
|
7c7f29 |
+import time
|
|
|
7c7f29 |
+import ldap
|
|
|
7c7f29 |
+import logging
|
|
|
7c7f29 |
+import pytest
|
|
|
7c7f29 |
+from lib389 import DirSrv, Entry, tools, tasks
|
|
|
7c7f29 |
+from lib389.tools import DirSrvTools
|
|
|
7c7f29 |
+from lib389._constants import *
|
|
|
7c7f29 |
+from lib389.properties import *
|
|
|
7c7f29 |
+from lib389.tasks import *
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
+log = logging.getLogger(__name__)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+from lib389.config import RSA, Encryption, Config
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+DEBUGGING = False
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+if DEBUGGING:
|
|
|
7c7f29 |
+ logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
+else:
|
|
|
7c7f29 |
+ logging.getLogger(__name__).setLevel(logging.INFO)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+log = logging.getLogger(__name__)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+class TopologyStandalone(object):
|
|
|
7c7f29 |
+ """The DS Topology Class"""
|
|
|
7c7f29 |
+ def __init__(self, standalone):
|
|
|
7c7f29 |
+ """Init"""
|
|
|
7c7f29 |
+ standalone.open()
|
|
|
7c7f29 |
+ self.standalone = standalone
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+@pytest.fixture(scope="module")
|
|
|
7c7f29 |
+def topology(request):
|
|
|
7c7f29 |
+ """Create DS Deployment"""
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Creating standalone instance ...
|
|
|
7c7f29 |
+ if DEBUGGING:
|
|
|
7c7f29 |
+ standalone = DirSrv(verbose=True)
|
|
|
7c7f29 |
+ else:
|
|
|
7c7f29 |
+ standalone = DirSrv(verbose=False)
|
|
|
7c7f29 |
+ args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
7c7f29 |
+ args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
7c7f29 |
+ args_standalone = args_instance.copy()
|
|
|
7c7f29 |
+ standalone.allocate(args_standalone)
|
|
|
7c7f29 |
+ instance_standalone = standalone.exists()
|
|
|
7c7f29 |
+ if instance_standalone:
|
|
|
7c7f29 |
+ standalone.delete()
|
|
|
7c7f29 |
+ standalone.create()
|
|
|
7c7f29 |
+ standalone.open()
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Deploy certs
|
|
|
7c7f29 |
+ # This is a trick. The nss db that ships with DS is broken
|
|
|
7c7f29 |
+ for f in ('key3.db', 'cert8.db', 'key4.db', 'cert9.db', 'secmod.db', 'pkcs11.txt'):
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ os.remove("%s/%s" % (topology.standalone.confdir, f ))
|
|
|
7c7f29 |
+ except:
|
|
|
7c7f29 |
+ pass
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ assert(standalone.nss_ssl.reinit() is True)
|
|
|
7c7f29 |
+ assert(standalone.nss_ssl.create_rsa_ca() is True)
|
|
|
7c7f29 |
+ assert(standalone.nss_ssl.create_rsa_key_and_cert() is True)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Say that we accept the cert
|
|
|
7c7f29 |
+ # Connect again!
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Enable the SSL options
|
|
|
7c7f29 |
+ standalone.rsa.create()
|
|
|
7c7f29 |
+ standalone.rsa.set('nsSSLPersonalitySSL', 'Server-Cert')
|
|
|
7c7f29 |
+ standalone.rsa.set('nsSSLToken', 'internal (software)')
|
|
|
7c7f29 |
+ standalone.rsa.set('nsSSLActivation', 'on')
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ standalone.config.set('nsslapd-secureport', PORT_STANDALONE2)
|
|
|
7c7f29 |
+ standalone.config.set('nsslapd-security', 'on')
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ standalone.restart()
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ def fin():
|
|
|
7c7f29 |
+ """If we are debugging just stop the instances, otherwise remove
|
|
|
7c7f29 |
+ them
|
|
|
7c7f29 |
+ """
|
|
|
7c7f29 |
+ if DEBUGGING:
|
|
|
7c7f29 |
+ standalone.stop()
|
|
|
7c7f29 |
+ else:
|
|
|
7c7f29 |
+ standalone.delete()
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ request.addfinalizer(fin)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Clear out the tmp dir
|
|
|
7c7f29 |
+ standalone.clearTmpDir(__file__)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ return TopologyStandalone(standalone)
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+def _create_user(inst):
|
|
|
7c7f29 |
+ inst.add_s(Entry((
|
|
|
7c7f29 |
+ USER_DN, {
|
|
|
7c7f29 |
+ 'objectClass': 'top account simplesecurityobject'.split(),
|
|
|
7c7f29 |
+ 'uid': 'user',
|
|
|
7c7f29 |
+ 'userpassword': 'password'
|
|
|
7c7f29 |
+ })))
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+def test_pwdPolicy_constraint(topology):
|
|
|
7c7f29 |
+ '''
|
|
|
7c7f29 |
+ Password policy test: Ensure that on a password change, the policy is
|
|
|
7c7f29 |
+ enforced correctly.
|
|
|
7c7f29 |
+ '''
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+ # Create a user
|
|
|
7c7f29 |
+ _create_user(topology.standalone)
|
|
|
7c7f29 |
+ # Set the password policy globally
|
|
|
7c7f29 |
+ topology.standalone.config.set('passwordMinLength', '10')
|
|
|
7c7f29 |
+ topology.standalone.config.set('passwordMinDigits', '2')
|
|
|
7c7f29 |
+ topology.standalone.config.set('passwordCheckSyntax', 'on')
|
|
|
7c7f29 |
+ topology.standalone.config.set('nsslapd-pwpolicy-local', 'off')
|
|
|
7c7f29 |
+ # Now open a new ldap connection with TLS
|
|
|
7c7f29 |
+ userconn = ldap.initialize("ldap://%s:%s" % (HOST_STANDALONE, PORT_STANDALONE))
|
|
|
7c7f29 |
+ userconn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap. OPT_X_TLS_NEVER )
|
|
|
7c7f29 |
+ userconn.start_tls_s()
|
|
|
7c7f29 |
+ userconn.simple_bind_s(USER_DN, 'password')
|
|
|
7c7f29 |
+ # This should have an exception!
|
|
|
7c7f29 |
+ try:
|
|
|
7c7f29 |
+ userconn.passwd_s(USER_DN, 'password', 'password1')
|
|
|
7c7f29 |
+ assert(False)
|
|
|
7c7f29 |
+ except ldap.CONSTRAINT_VIOLATION:
|
|
|
7c7f29 |
+ assert(True)
|
|
|
7c7f29 |
+ # Change the password to something invalid!
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+
|
|
|
7c7f29 |
+if __name__ == '__main__':
|
|
|
7c7f29 |
+ # Run isolated
|
|
|
7c7f29 |
+ # -s for DEBUG mode
|
|
|
7c7f29 |
+ CURRENT_FILE = os.path.realpath(__file__)
|
|
|
7c7f29 |
+ pytest.main("-s %s" % CURRENT_FILE)
|
|
|
7c7f29 |
diff --git a/dirsrvtests/tests/suites/password/pwdPolicy_test.py b/dirsrvtests/tests/suites/password/pwdPolicy_test.py
|
|
|
7c7f29 |
deleted file mode 100644
|
|
|
7c7f29 |
index 653d033..0000000
|
|
|
7c7f29 |
--- a/dirsrvtests/tests/suites/password/pwdPolicy_test.py
|
|
|
7c7f29 |
+++ /dev/null
|
|
|
7c7f29 |
@@ -1,151 +0,0 @@
|
|
|
7c7f29 |
-# --- BEGIN COPYRIGHT BLOCK ---
|
|
|
7c7f29 |
-# Copyright (C) 2015 Red Hat, Inc.
|
|
|
7c7f29 |
-# All rights reserved.
|
|
|
7c7f29 |
-#
|
|
|
7c7f29 |
-# License: GPL (version 3 or any later version).
|
|
|
7c7f29 |
-# See LICENSE for details.
|
|
|
7c7f29 |
-# --- END COPYRIGHT BLOCK ---
|
|
|
7c7f29 |
-#
|
|
|
7c7f29 |
-import os
|
|
|
7c7f29 |
-import sys
|
|
|
7c7f29 |
-import time
|
|
|
7c7f29 |
-import ldap
|
|
|
7c7f29 |
-import logging
|
|
|
7c7f29 |
-import pytest
|
|
|
7c7f29 |
-from lib389 import DirSrv, Entry, tools, tasks
|
|
|
7c7f29 |
-from lib389.tools import DirSrvTools
|
|
|
7c7f29 |
-from lib389._constants import *
|
|
|
7c7f29 |
-from lib389.properties import *
|
|
|
7c7f29 |
-from lib389.tasks import *
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
-log = logging.getLogger(__name__)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-from lib389.config import RSA, Encryption, Config
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-DEBUGGING = False
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-USER_DN = 'uid=user,ou=People,%s' % DEFAULT_SUFFIX
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-if DEBUGGING:
|
|
|
7c7f29 |
- logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
-else:
|
|
|
7c7f29 |
- logging.getLogger(__name__).setLevel(logging.INFO)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-log = logging.getLogger(__name__)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-class TopologyStandalone(object):
|
|
|
7c7f29 |
- """The DS Topology Class"""
|
|
|
7c7f29 |
- def __init__(self, standalone):
|
|
|
7c7f29 |
- """Init"""
|
|
|
7c7f29 |
- standalone.open()
|
|
|
7c7f29 |
- self.standalone = standalone
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-@pytest.fixture(scope="module")
|
|
|
7c7f29 |
-def topology(request):
|
|
|
7c7f29 |
- """Create DS Deployment"""
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Creating standalone instance ...
|
|
|
7c7f29 |
- if DEBUGGING:
|
|
|
7c7f29 |
- standalone = DirSrv(verbose=True)
|
|
|
7c7f29 |
- else:
|
|
|
7c7f29 |
- standalone = DirSrv(verbose=False)
|
|
|
7c7f29 |
- args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
7c7f29 |
- args_standalone = args_instance.copy()
|
|
|
7c7f29 |
- standalone.allocate(args_standalone)
|
|
|
7c7f29 |
- instance_standalone = standalone.exists()
|
|
|
7c7f29 |
- if instance_standalone:
|
|
|
7c7f29 |
- standalone.delete()
|
|
|
7c7f29 |
- standalone.create()
|
|
|
7c7f29 |
- standalone.open()
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Deploy certs
|
|
|
7c7f29 |
- # This is a trick. The nss db that ships with DS is broken
|
|
|
7c7f29 |
- for f in ('key3.db', 'cert8.db', 'key4.db', 'cert9.db', 'secmod.db', 'pkcs11.txt'):
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- os.remove("%s/%s" % (topology.standalone.confdir, f ))
|
|
|
7c7f29 |
- except:
|
|
|
7c7f29 |
- pass
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- assert(standalone.nss_ssl.reinit() is True)
|
|
|
7c7f29 |
- assert(standalone.nss_ssl.create_rsa_ca() is True)
|
|
|
7c7f29 |
- assert(standalone.nss_ssl.create_rsa_key_and_cert() is True)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Say that we accept the cert
|
|
|
7c7f29 |
- # Connect again!
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Enable the SSL options
|
|
|
7c7f29 |
- standalone.rsa.create()
|
|
|
7c7f29 |
- standalone.rsa.set('nsSSLPersonalitySSL', 'Server-Cert')
|
|
|
7c7f29 |
- standalone.rsa.set('nsSSLToken', 'internal (software)')
|
|
|
7c7f29 |
- standalone.rsa.set('nsSSLActivation', 'on')
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- standalone.config.set('nsslapd-secureport', PORT_STANDALONE2)
|
|
|
7c7f29 |
- standalone.config.set('nsslapd-security', 'on')
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- standalone.restart()
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- def fin():
|
|
|
7c7f29 |
- """If we are debugging just stop the instances, otherwise remove
|
|
|
7c7f29 |
- them
|
|
|
7c7f29 |
- """
|
|
|
7c7f29 |
- if DEBUGGING:
|
|
|
7c7f29 |
- standalone.stop()
|
|
|
7c7f29 |
- else:
|
|
|
7c7f29 |
- standalone.delete()
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- request.addfinalizer(fin)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Clear out the tmp dir
|
|
|
7c7f29 |
- standalone.clearTmpDir(__file__)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- return TopologyStandalone(standalone)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-def _create_user(inst):
|
|
|
7c7f29 |
- inst.add_s(Entry((
|
|
|
7c7f29 |
- USER_DN, {
|
|
|
7c7f29 |
- 'objectClass': 'top account simplesecurityobject'.split(),
|
|
|
7c7f29 |
- 'uid': 'user',
|
|
|
7c7f29 |
- 'userpassword': 'password'
|
|
|
7c7f29 |
- })))
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-def test_pwdPolicy_constraint(topology):
|
|
|
7c7f29 |
- '''
|
|
|
7c7f29 |
- Password policy test: Ensure that on a password change, the policy is
|
|
|
7c7f29 |
- enforced correctly.
|
|
|
7c7f29 |
- '''
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Create a user
|
|
|
7c7f29 |
- _create_user(topology.standalone)
|
|
|
7c7f29 |
- # Set the password policy globally
|
|
|
7c7f29 |
- topology.standalone.config.set('passwordMinLength', '10')
|
|
|
7c7f29 |
- topology.standalone.config.set('passwordMinDigits', '2')
|
|
|
7c7f29 |
- topology.standalone.config.set('passwordCheckSyntax', 'on')
|
|
|
7c7f29 |
- topology.standalone.config.set('nsslapd-pwpolicy-local', 'off')
|
|
|
7c7f29 |
- # Now open a new ldap connection with TLS
|
|
|
7c7f29 |
- userconn = ldap.initialize("ldap://%s:%s" % (HOST_STANDALONE, PORT_STANDALONE))
|
|
|
7c7f29 |
- userconn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap. OPT_X_TLS_NEVER )
|
|
|
7c7f29 |
- userconn.start_tls_s()
|
|
|
7c7f29 |
- userconn.simple_bind_s(USER_DN, 'password')
|
|
|
7c7f29 |
- # This should have an exception!
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- userconn.passwd_s(USER_DN, 'password', 'password1')
|
|
|
7c7f29 |
- assert(False)
|
|
|
7c7f29 |
- except ldap.CONSTRAINT_VIOLATION:
|
|
|
7c7f29 |
- assert(True)
|
|
|
7c7f29 |
- # Change the password to something invalid!
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-if __name__ == '__main__':
|
|
|
7c7f29 |
- # Run isolated
|
|
|
7c7f29 |
- # -s for DEBUG mode
|
|
|
7c7f29 |
- CURRENT_FILE = os.path.realpath(__file__)
|
|
|
7c7f29 |
- pytest.main("-s %s" % CURRENT_FILE)
|
|
|
7c7f29 |
diff --git a/dirsrvtests/tests/suites/password/pwd_change_policytest.py b/dirsrvtests/tests/suites/password/pwd_change_policytest.py
|
|
|
7c7f29 |
deleted file mode 100644
|
|
|
7c7f29 |
index 1d48c65..0000000
|
|
|
7c7f29 |
--- a/dirsrvtests/tests/suites/password/pwd_change_policytest.py
|
|
|
7c7f29 |
+++ /dev/null
|
|
|
7c7f29 |
@@ -1,240 +0,0 @@
|
|
|
7c7f29 |
-import os
|
|
|
7c7f29 |
-import sys
|
|
|
7c7f29 |
-import time
|
|
|
7c7f29 |
-import subprocess
|
|
|
7c7f29 |
-import ldap
|
|
|
7c7f29 |
-import logging
|
|
|
7c7f29 |
-import pytest
|
|
|
7c7f29 |
-from lib389 import DirSrv, Entry, tools, tasks
|
|
|
7c7f29 |
-from lib389.tools import DirSrvTools
|
|
|
7c7f29 |
-from lib389._constants import *
|
|
|
7c7f29 |
-from lib389.properties import *
|
|
|
7c7f29 |
-from lib389.tasks import *
|
|
|
7c7f29 |
-from lib389.utils import *
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-DEBUGGING = False
|
|
|
7c7f29 |
-OU_PEOPLE = 'ou=people,{}'.format(DEFAULT_SUFFIX)
|
|
|
7c7f29 |
-TEST_USER_NAME = 'simplepaged_test'
|
|
|
7c7f29 |
-TEST_USER_DN = 'uid={},{}'.format(TEST_USER_NAME, OU_PEOPLE)
|
|
|
7c7f29 |
-TEST_USER_PWD = 'simplepaged_test'
|
|
|
7c7f29 |
-PW_POLICY_CONT_USER = 'cn="cn=nsPwPolicyEntry,uid=simplepaged_test,'\
|
|
|
7c7f29 |
- 'ou=people,dc=example,dc=com",'\
|
|
|
7c7f29 |
- 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
|
|
|
7c7f29 |
-PW_POLICY_CONT_PEOPLE = 'cn="cn=nsPwPolicyEntry,'\
|
|
|
7c7f29 |
- 'ou=people,dc=example,dc=com",'\
|
|
|
7c7f29 |
- 'cn=nsPwPolicyContainer,ou=people,dc=example,dc=com'
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-if DEBUGGING:
|
|
|
7c7f29 |
- logging.getLogger(__name__).setLevel(logging.DEBUG)
|
|
|
7c7f29 |
-else:
|
|
|
7c7f29 |
- logging.getLogger(__name__).setLevel(logging.INFO)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-log = logging.getLogger(__name__)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-class TopologyStandalone(object):
|
|
|
7c7f29 |
- """The DS Topology Class"""
|
|
|
7c7f29 |
- def __init__(self, standalone):
|
|
|
7c7f29 |
- """Init"""
|
|
|
7c7f29 |
- standalone.open()
|
|
|
7c7f29 |
- self.standalone = standalone
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-@pytest.fixture(scope="module")
|
|
|
7c7f29 |
-def topology(request):
|
|
|
7c7f29 |
- """Create DS Deployment"""
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- # Creating standalone instance ...
|
|
|
7c7f29 |
- if DEBUGGING:
|
|
|
7c7f29 |
- standalone = DirSrv(verbose=True)
|
|
|
7c7f29 |
- else:
|
|
|
7c7f29 |
- standalone = DirSrv(verbose=False)
|
|
|
7c7f29 |
- args_instance[SER_HOST] = HOST_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_PORT] = PORT_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_SERVERID_PROP] = SERVERID_STANDALONE
|
|
|
7c7f29 |
- args_instance[SER_CREATION_SUFFIX] = DEFAULT_SUFFIX
|
|
|
7c7f29 |
- args_standalone = args_instance.copy()
|
|
|
7c7f29 |
- standalone.allocate(args_standalone)
|
|
|
7c7f29 |
- instance_standalone = standalone.exists()
|
|
|
7c7f29 |
- if instance_standalone:
|
|
|
7c7f29 |
- standalone.delete()
|
|
|
7c7f29 |
- standalone.create()
|
|
|
7c7f29 |
- standalone.open()
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- def fin():
|
|
|
7c7f29 |
- """If we are debugging just stop the instances, otherwise remove
|
|
|
7c7f29 |
- them
|
|
|
7c7f29 |
- """
|
|
|
7c7f29 |
- if DEBUGGING:
|
|
|
7c7f29 |
- standalone.stop()
|
|
|
7c7f29 |
- else:
|
|
|
7c7f29 |
- standalone.delete()
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- request.addfinalizer(fin)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- return TopologyStandalone(standalone)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-@pytest.fixture(scope="module")
|
|
|
7c7f29 |
-def test_user(topology, request):
|
|
|
7c7f29 |
- """User for binding operation"""
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Adding user {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.add_s(Entry((TEST_USER_DN, {
|
|
|
7c7f29 |
- 'objectclass': 'top person'.split(),
|
|
|
7c7f29 |
- 'objectclass': 'organizationalPerson',
|
|
|
7c7f29 |
- 'objectclass': 'inetorgperson',
|
|
|
7c7f29 |
- 'cn': TEST_USER_NAME,
|
|
|
7c7f29 |
- 'sn': TEST_USER_NAME,
|
|
|
7c7f29 |
- 'userpassword': TEST_USER_PWD,
|
|
|
7c7f29 |
- 'mail': '%s@redhat.com' % TEST_USER_NAME,
|
|
|
7c7f29 |
- 'uid': TEST_USER_NAME
|
|
|
7c7f29 |
- })))
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to add user (%s): error (%s)' % (TEST_USER_DN,
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- def fin():
|
|
|
7c7f29 |
- log.info('Deleting user {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
- topology.standalone.delete_s(TEST_USER_DN)
|
|
|
7c7f29 |
- request.addfinalizer(fin)
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-@pytest.fixture(scope="module")
|
|
|
7c7f29 |
-def password_policy(topology, test_user):
|
|
|
7c7f29 |
- """Set up password policy for subtree and user"""
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Enable fine-grained policy')
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.modify_s(DN_CONFIG, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'nsslapd-pwpolicy-local',
|
|
|
7c7f29 |
- 'on')])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to set fine-grained policy: error {}'.format(
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Create password policy for subtree {}'.format(OU_PEOPLE))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- subprocess.call(['ns-newpwpolicy.pl', '-D', DN_DM, '-w', PASSWORD,
|
|
|
7c7f29 |
- '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
|
|
|
7c7f29 |
- '-S', OU_PEOPLE, '-Z', SERVERID_STANDALONE])
|
|
|
7c7f29 |
- except subprocess.CalledProcessError as e:
|
|
|
7c7f29 |
- log.error('Failed to create pw policy policy for {}: error {}'.format(
|
|
|
7c7f29 |
- OU_PEOPLE, e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Add pwdpolicysubentry attribute to {}'.format(OU_PEOPLE))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.modify_s(OU_PEOPLE, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'pwdpolicysubentry',
|
|
|
7c7f29 |
- PW_POLICY_CONT_PEOPLE)])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to pwdpolicysubentry pw policy '\
|
|
|
7c7f29 |
- 'policy for {}: error {}'.format(OU_PEOPLE,
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Create password policy for subtree {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- subprocess.call(['ns-newpwpolicy.pl', '-D', DN_DM, '-w', PASSWORD,
|
|
|
7c7f29 |
- '-p', str(PORT_STANDALONE), '-h', HOST_STANDALONE,
|
|
|
7c7f29 |
- '-U', TEST_USER_DN, '-Z', SERVERID_STANDALONE])
|
|
|
7c7f29 |
- except subprocess.CalledProcessError as e:
|
|
|
7c7f29 |
- log.error('Failed to create pw policy policy for {}: error {}'.format(
|
|
|
7c7f29 |
- TEST_USER_DN, e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Add pwdpolicysubentry attribute to {}'.format(TEST_USER_DN))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'pwdpolicysubentry',
|
|
|
7c7f29 |
- PW_POLICY_CONT_USER)])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to pwdpolicysubentry pw policy '\
|
|
|
7c7f29 |
- 'policy for {}: error {}'.format(TEST_USER_DN,
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-@pytest.mark.parametrize('subtree_pwchange,user_pwchange,exception',
|
|
|
7c7f29 |
- [('off', 'on', None), ('on', 'on', None),
|
|
|
7c7f29 |
- ('on', 'off', ldap.UNWILLING_TO_PERFORM),
|
|
|
7c7f29 |
- ('off', 'off', ldap.UNWILLING_TO_PERFORM)])
|
|
|
7c7f29 |
-def test_change_pwd(topology, test_user, password_policy,
|
|
|
7c7f29 |
- subtree_pwchange, user_pwchange, exception):
|
|
|
7c7f29 |
- """Verify that 'passwordChange' attr works as expected
|
|
|
7c7f29 |
- User should have a priority over a subtree.
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- :Feature: Password policy
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- :Setup: Standalone instance, test user,
|
|
|
7c7f29 |
- password policy entries for a user and a subtree
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- :Steps: 1. Set passwordChange on the user and the subtree
|
|
|
7c7f29 |
- to various combinations
|
|
|
7c7f29 |
- 2. Bind as test user
|
|
|
7c7f29 |
- 3. Try to change password
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- :Assert: Subtree/User passwordChange - result
|
|
|
7c7f29 |
- off/on, on/on - success
|
|
|
7c7f29 |
- on/off, off/off - UNWILLING_TO_PERFORM
|
|
|
7c7f29 |
- """
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Set passwordChange to "{}" - {}'.format(subtree_pwchange,
|
|
|
7c7f29 |
- PW_POLICY_CONT_PEOPLE))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.modify_s(PW_POLICY_CONT_PEOPLE, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'passwordChange',
|
|
|
7c7f29 |
- subtree_pwchange)])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to set passwordChange '\
|
|
|
7c7f29 |
- 'policy for {}: error {}'.format(PW_POLICY_CONT_PEOPLE,
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- log.info('Set passwordChange to "{}" - {}'.format(user_pwchange,
|
|
|
7c7f29 |
- PW_POLICY_CONT_USER))
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- topology.standalone.modify_s(PW_POLICY_CONT_USER, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'passwordChange',
|
|
|
7c7f29 |
- user_pwchange)])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to set passwordChange '\
|
|
|
7c7f29 |
- 'policy for {}: error {}'.format(PW_POLICY_CONT_USER,
|
|
|
7c7f29 |
- e.message['desc']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
- try:
|
|
|
7c7f29 |
- log.info('Bind as user and modify userPassword')
|
|
|
7c7f29 |
- topology.standalone.simple_bind_s(TEST_USER_DN, TEST_USER_PWD)
|
|
|
7c7f29 |
- if exception:
|
|
|
7c7f29 |
- with pytest.raises(exception):
|
|
|
7c7f29 |
- topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'userPassword',
|
|
|
7c7f29 |
- 'new_pass')])
|
|
|
7c7f29 |
- else:
|
|
|
7c7f29 |
- topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'userPassword',
|
|
|
7c7f29 |
- 'new_pass')])
|
|
|
7c7f29 |
- except ldap.LDAPError as e:
|
|
|
7c7f29 |
- log.error('Failed to change userpassword for {}: error {}'.format(
|
|
|
7c7f29 |
- TEST_USER_DN, e.message['info']))
|
|
|
7c7f29 |
- raise e
|
|
|
7c7f29 |
- finally:
|
|
|
7c7f29 |
- log.info('Bind as DM')
|
|
|
7c7f29 |
- topology.standalone.simple_bind_s(DN_DM, PASSWORD)
|
|
|
7c7f29 |
- topology.standalone.modify_s(TEST_USER_DN, [(ldap.MOD_REPLACE,
|
|
|
7c7f29 |
- 'userPassword',
|
|
|
7c7f29 |
- TEST_USER_PWD)])
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-
|
|
|
7c7f29 |
-if __name__ == '__main__':
|
|
|
7c7f29 |
- # Run isolated
|
|
|
7c7f29 |
- # -s for DEBUG mode
|
|
|
7c7f29 |
- CURRENT_FILE = os.path.realpath(__file__)
|
|
|
7c7f29 |
- pytest.main("-s %s" % CURRENT_FILE)
|
|
|
7c7f29 |
--
|
|
|
7c7f29 |
2.4.11
|
|
|
7c7f29 |
|