From 3a68f83b59fff17ec9c3c296b12895db0daa30c4 Mon Sep 17 00:00:00 2001 From: Sankar Ramalingam Date: Sun, 24 Sep 2017 01:24:14 +0530 Subject: [PATCH] Ticket #48085 - CI tests - replication encryption cl5 Description: Adding encryption changelog tests. Master1 with changelog encryption and Master2 with clear text password. Master1's changelog is expected to contain the encrypted value for unhashed#user#password attribute and Master2 should contain clear text password. https://pagure.io/389-ds-base/issue/48085 Reviewed by: ? --- .../suites/replication/encryption_cl5_test.py | 192 +++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 dirsrvtests/tests/suites/replication/encryption_cl5_test.py diff --git a/dirsrvtests/tests/suites/replication/encryption_cl5_test.py b/dirsrvtests/tests/suites/replication/encryption_cl5_test.py new file mode 100644 index 000000000..e5164788c --- /dev/null +++ b/dirsrvtests/tests/suites/replication/encryption_cl5_test.py @@ -0,0 +1,192 @@ +# --- BEGIN COPYRIGHT BLOCK --- +# Copyright (C) 2017 Red Hat, Inc. +# All rights reserved. +# +# License: GPL (version 3 or any later version). +# See LICENSE for details. +# --- END COPYRIGHT BLOCK --- +# +import os +import logging +import ldap +import pytest +from lib389.utils import generate_ds_params +from lib389.dseldif import DSEldif +from lib389.idm.user import UserAccounts +from lib389.properties import TASK_WAIT +from lib389.topologies import topology_m2 as topo +from lib389._constants import * + +ATTRIBUTE = 'unhashed#user#password' +USER_PROPERTIES = { + 'uid': 'encrypt1usr', + 'cn': 'encrypt1usr', + 'sn': 'encrypt1usr', + 'uidNumber': '1001', + 'gidNumber': '2001', + 'userpassword': PASSWORD, + 'description': 'userdesc', + 'homeDirectory': '/home/testuser' +} + +DEBUGGING = os.getenv("DEBUGGING", default=False) +if DEBUGGING: + logging.getLogger(__name__).setLevel(logging.DEBUG) +else: + logging.getLogger(__name__).setLevel(logging.INFO) +log = logging.getLogger(__name__) + + +@pytest.fixture(scope='module') +def enable_ssl_masters(topo, request): + """Configure SSL for all masters""" + + log.info('Enabling SSL for all masters') + for master in topo.ms.values(): + inst_num = int(master.serverid.split("master")[1]) + instance_data = generate_ds_params(inst_num, ReplicaRole.MASTER) + secure_port = instance_data[SER_SECURE_PORT] + + master.stop() + assert master.nss_ssl.reinit() is True + assert master.nss_ssl.create_rsa_ca() is True + assert master.nss_ssl.create_rsa_key_and_cert() is True + master.start() + + master.rsa.create() + master.config.set('nsslapd-secureport', str(secure_port)) + master.config.set('nsslapd-security', 'on') + # master.sslport = secure_port + # master.restart(post_open=False) + + def fin(): + log.info('Disabling SSL for master1 and master2') + for master in topo.ms.values(): + master.config.set('nsslapd-security', 'off') + master.rsa.delete() + + request.addfinalizer(fin) + + +@pytest.fixture(scope='module') +def enable_changelog_encryption(topo, request): + """Configure changelog encryption for master1""" + + log.info('Configuring changelog encryption for master1') + topo.ms['master1'].stop() + dse_ldif = DSEldif(topo.ms['master1']) + try: + dse_ldif.replace(DN_CHANGELOG, 'nsslapd-encryptionalgorithm', 'AES') + except: + log.error('Failed to add nsslapd-encryptionalgorithm value AES') + raise + topo.ms['master1'].start() + + +def _check_unhashed_userpw_encrypted(topo, change_type, inst_name, user_dn, user_pw, is_encrypted): + """Check if unhashed#user#password attribute value is encrypted""" + + master = topo.ms['{}'.format(inst_name)] + changelog_dbdir = os.path.join(os.path.dirname(master.dbdir), DEFAULT_CHANGELOG_DB) + for files in os.listdir(changelog_dbdir): + if files.endswith('.db'): + changelog_dbfile = os.path.join(changelog_dbdir, files) + log.info('Changelog dbfile file exist: {}'.format(changelog_dbfile)) + log.info('Running dbscan -f to check {} attr'.format(ATTRIBUTE)) + dbscanOut = master.dbscan(DEFAULT_CHANGELOG_DB, changelog_dbfile) + count = 0 + for entry in dbscanOut.split('dbid: '): + if 'operation: ' + change_type in entry and ATTRIBUTE in entry and user_dn in entry: + count += 1 + if is_encrypted: + if ATTRIBUTE + ': ' + user_pw in entry: + log.fatal('Changelog entry contains clear text password') + assert False + else: + if not ATTRIBUTE + ': ' + user_pw in entry: + log.fatal('Changelog entry does not contain clear text password') + assert False + if not count: + log.fatal('Operation type and DN of the entry not matched in changelog') + assert False + + +def test_encrypt_unhashed_user_passw_m1(topo, enable_ssl_masters, enable_changelog_encryption): + """Add/modify userPassword in M1 and check if unhashed#user#password attr is encrypted + + :id: b7a37bf8-4b2e-4dbd-9891-70117d67558c + :setup: Two masters and a consumer with SSL. + Changelog encryption in M1 + :steps: 1. Add user to Master1 + 2. Run dbscan -f on M1 to check unhashed#user#password attribute is encrypted. + 3. Run dbscan -f on M2 to check unhashed#user#password attribute is in cleartext. + 4. Modify password in M2. + 5. Run dbscan -f on M1 to check unhashed#user#password attribute is encrypted. + 6. Run dbscan -f on M2 to check unhashed#user#password attribute is in cleartext. + :expectedresults: + 1. Add user to M1 should PASS. + 2. Unhashed#user#password attribute in M1 should be encrypted. + 3. Unhashed#user#password attribute in M2 should be in cleartext. + 4. Modify password in M2 should PASS. + 5. Unhashed#user#password attribute in M1 should be encrypted. + 6. Unhashed#user#password attribute in M2 should be in cleartext. + """ + + test_entry = 'test1encrypt' + USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn', 'sn'], test_entry)) + log.info('Adding user: {} to master1'.format(test_entry)) + users = UserAccounts(topo.ms['master1'], DEFAULT_SUFFIX) + tuser = users.create(properties=USER_PROPERTIES) + + _check_unhashed_userpw_encrypted(topo, 'add', 'master1', tuser.dn, PASSWORD, True) + _check_unhashed_userpw_encrypted(topo, 'add', 'master2', tuser.dn, PASSWORD, False) + + log.info('Reset password from M2 and check unhashed#user#password') + tuser.set('userPassword', 'm1Test123') + _check_unhashed_userpw_encrypted(topo, 'modify', 'master1', tuser.dn, 'm1Test123', True) + _check_unhashed_userpw_encrypted(topo, 'modify', 'master2', tuser.dn, 'm1Test123', False) + tuser.delete() + + +def test_encrypt_unhashed_user_passw_m2(topo, enable_ssl_masters, enable_changelog_encryption): + """Add/modify userPassword in M2 and check if unhashed#user#password attr is encrypted + + :id: b7a37bf8-4b2e-4dbd-9891-70117d67558c + :setup: Two masters and a consumer with SSL. + Changelog encryption in M1 + :steps: 1. Add user to Master2 + 2. Run dbscan -f on M1 to check unhashed#user#password attribute is encrypted. + 3. Run dbscan -f on M2 to check unhashed#user#password attribute is in cleartext. + 4. Modify password in M1. + 5. Run dbscan -f on M1 to check unhashed#user#password attribute is encrypted. + 6. Run dbscan -f on M2 to check unhashed#user#password attribute is in cleartext. + :expectedresults: + 1. Add user to M2 should PASS. + 2. Unhashed#user#password attribute in M1 should be encrypted. + 3. Unhashed#user#password attribute in M2 should be in cleartext. + 4. Modify password in M1 should PASS. + 5. Unhashed#user#password attribute in M1 should be encrypted. + 6. Unhashed#user#password attribute in M2 should be in cleartext. + """ + + test_entry = 'test2encrypt' + USER_PROPERTIES.update(dict.fromkeys(['uid', 'cn', 'sn'], test_entry)) + log.info('Adding user: {} to master2'.format(test_entry)) + users = UserAccounts(topo.ms['master2'], DEFAULT_SUFFIX) + tuser = users.create(properties=USER_PROPERTIES) + + _check_unhashed_userpw_encrypted(topo, 'add', 'master1', tuser.dn, PASSWORD, True) + _check_unhashed_userpw_encrypted(topo, 'add', 'master2', tuser.dn, PASSWORD, False) + + log.info('Reset password from M1 and check unhashed#user#password') + tuser.set('userPassword', 'm2Test123') + _check_unhashed_userpw_encrypted(topo, 'modify', 'master1', tuser.dn, 'm2Test123', True) + _check_unhashed_userpw_encrypted(topo, 'modify', 'master2', tuser.dn, 'm2Test123', False) + tuser.delete() + + +if __name__ == '__main__': + # Run isolated + # -s for DEBUG mode + CURRENT_FILE = os.path.realpath(__file__) + pytest.main("-s {}".format(CURRENT_FILE)) -- 2.13.5