From d77f12671189ed15cb199acd104b831143757cc3 2020-05-08 13:14:09 From: Branko Majic Date: 2020-05-08 13:14:09 Subject: [PATCH] MAR-149: Fixed/refactored the ldap_server tests to be less dependant on ordering of returned LDAP entries. --- diff --git a/roles/ldap_server/molecule/default/tests/helpers.py b/roles/ldap_server/molecule/default/tests/helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..3bed75d6ecaaabb116ea00ccc595d4d491e71f27 --- /dev/null +++ b/roles/ldap_server/molecule/default/tests/helpers.py @@ -0,0 +1,31 @@ +import io + +import ldif + + +def parse_ldif(ldif_input): + """ + Helper function that parses the passed-in LDIF string. This is a + simple wrapper around the Python LDAP ldif.LDIFRecordList class. + + Entries are returned as list of (dn, attributes) + tuples. Attributes are represented by a dictionary mapping + attribute names to list of associated values. + + :param ldif_input: LDIF to parse. + :type ldif_input: str + + :returns: List of parsed entries. + :rtype: list[tuple(str, dict{str: list[str]})] + + Returns: + """ + + parser = ldif.LDIFRecordList(io.StringIO(ldif_input)) + + try: + parser.parse() + except Exception as e: + raise ValueError("Failed to parse input: %s" % str(e)) + + return parser.all_records diff --git a/roles/ldap_server/molecule/default/tests/test_default.py b/roles/ldap_server/molecule/default/tests/test_default.py index daee18588aeaa2412ab8962af2bea20764ad8bc6..4b95c6dc7ba4af12d35cc8e9e9b7fb4022d3a6f7 100644 --- a/roles/ldap_server/molecule/default/tests/test_default.py +++ b/roles/ldap_server/molecule/default/tests/test_default.py @@ -2,6 +2,8 @@ import os import testinfra.utils.ansible_runner +from helpers import parse_ldif + testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*') @@ -13,7 +15,7 @@ def test_installed_packages(host): """ assert host.package('slapd').is_installed - assert host.package('python-ldap').is_installed + assert host.package('python3-pyldap').is_installed def test_ldap_user_group(host): @@ -111,20 +113,25 @@ def test_basic_directory_structure(host): Tests if the base LDAP directory structure has been set-up correctly. """ - with host.sudo(): - - ous = ["people", "groups", "services"] - - for ou in ous: + expected_entries = parse_ldif(""" +dn: ou=people,dc=local +objectClass: organizationalUnit +ou: people - entry = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b ou=%s,dc=local' % ou) +dn: ou=groups,dc=local +objectClass: organizationalUnit +ou: groups - assert entry.rc == 0 - assert entry.stdout == """dn: ou=%(ou)s,dc=local +dn: ou=services,dc=local objectClass: organizationalUnit -ou: %(ou)s +ou: services +""") -""" % {'ou': ou} + entry = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -b dc=local " + "'(|(entrydn=ou=people,dc=local)(entrydn=ou=groups,dc=local)(entrydn=ou=services,dc=local))'") + + assert entry.rc == 0 + assert parse_ldif(entry.stdout) == expected_entries def test_mail_service_entries(host): @@ -134,29 +141,23 @@ def test_mail_service_entries(host): with host.sudo(): - entry = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b ou=mail,ou=services,dc=local') - assert entry.rc == 0 - assert entry.stdout == """dn: ou=mail,ou=services,dc=local + expected_entries = parse_ldif(""" +dn: ou=mail,ou=services,dc=local objectClass: organizationalUnit ou: mail -""" +dn: ou=aliases,ou=mail,ou=services,dc=local +objectClass: organizationalUnit +ou: aliases - entry = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b ou=domains,ou=mail,ou=services,dc=local') - assert entry.rc == 0 - assert entry.stdout == """dn: ou=domains,ou=mail,ou=services,dc=local +dn: ou=domains,ou=mail,ou=services,dc=local objectClass: organizationalUnit ou: domains +""") -""" - - entry = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b ou=aliases,ou=mail,ou=services,dc=local') + entry = host.run('ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -b ou=mail,ou=services,dc=local') assert entry.rc == 0 - assert entry.stdout == """dn: ou=aliases,ou=mail,ou=services,dc=local -objectClass: organizationalUnit -ou: aliases - -""" + assert parse_ldif(entry.stdout) == expected_entries def test_firewall_configuration_file(host): diff --git a/roles/ldap_server/molecule/default/tests/test_helpers.py b/roles/ldap_server/molecule/default/tests/test_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..cbcc7e7757aea0e724da611e69f15acce00e7321 --- /dev/null +++ b/roles/ldap_server/molecule/default/tests/test_helpers.py @@ -0,0 +1,42 @@ +import pytest + +from helpers import parse_ldif + + +def test_parse_ldif_returns_empty_list_for_empty_ldif(): + ldif = "" + assert parse_ldif(ldif) == [] + + +def test_parse_ldif_raises_exception_for_invalid_ldif(): + + with pytest.raises(ValueError): + parse_ldif("dn: john") + + +def test_parse_ldif_returns_parsed_entries_for_valid_ldif(): + + ldif = """ +dn: uid=john,ou=people +uid: john + +dn: uid=jane,ou=people +uid: jane +""" + + expected_entry = [ + ( + "uid=john,ou=people", { + "uid": [b"john"], + } + ), + ( + "uid=jane,ou=people", { + "uid": [b"jane"] + }, + ), + ] + + entry = parse_ldif(ldif) + + assert entry == expected_entry diff --git a/roles/ldap_server/molecule/default/tests/test_optional.py b/roles/ldap_server/molecule/default/tests/test_optional.py index a2d7b8b2e281a0d4e6197010e62ca3277408d476..4133ff49f715c1e765ed07f35cbe72e5429fc0bd 100644 --- a/roles/ldap_server/molecule/default/tests/test_optional.py +++ b/roles/ldap_server/molecule/default/tests/test_optional.py @@ -2,6 +2,8 @@ import os import testinfra.utils.ansible_runner +from helpers import parse_ldif + testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-optional') @@ -149,10 +151,8 @@ def test_services_login_entries(host): with host.sudo(): - entries = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s one -b ou=services,dc=local '(objectClass=simpleSecurityObject)'") - - assert entries.rc == 0 - assert entries.stdout == """dn: cn=consumer1,ou=services,dc=local + expected_entries = parse_ldif(""" +dn: cn=consumer1,ou=services,dc=local objectClass: applicationProcess objectClass: simpleSecurityObject userPassword:: Y29uc3VtZXIxcGFzc3dvcmQ= @@ -163,8 +163,12 @@ objectClass: applicationProcess objectClass: simpleSecurityObject userPassword:: Y29uc3VtZXIycGFzc3dvcmQ= cn: consumer2 +""") -""" + entries = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s one -b ou=services,dc=local '(objectClass=simpleSecurityObject)'") + + assert entries.rc == 0 + assert parse_ldif(entries.stdout) == expected_entries def test_group_entries(host): @@ -174,10 +178,8 @@ def test_group_entries(host): with host.sudo(): - entries = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s one -b ou=groups,dc=local '(objectClass=groupOfUniqueNames)'") - - assert entries.rc == 0 - assert entries.stdout == """dn: cn=group1,ou=groups,dc=local + expected_entries = parse_ldif(""" +dn: cn=group1,ou=groups,dc=local objectClass: groupOfUniqueNames uniqueMember: cn=NONE cn: group1 @@ -186,8 +188,12 @@ dn: cn=group2,ou=groups,dc=local objectClass: groupOfUniqueNames uniqueMember: cn=NONE cn: group2 +""") + + entries = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s one -b ou=groups,dc=local '(objectClass=groupOfUniqueNames)'") -""" + assert entries.rc == 0 + assert parse_ldif(entries.stdout) == expected_entries def test_user_supplied_entries(host): @@ -197,22 +203,24 @@ def test_user_supplied_entries(host): with host.sudo(): - john_doe = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b uid=john,dc=local") - assert john_doe.rc == 0 - assert sorted(john_doe.stdout.strip().split("\n")) == sorted("""dn: uid=john,dc=local + expected_entries = parse_ldif(""" +dn: uid=john,dc=local objectClass: inetOrgPerson objectClass: simpleSecurityObject userPassword:: am9obnBhc3N3b3Jk cn: John Doe sn: Doe -uid: john""".split("\n")) +uid: john - jane_doe = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -s base -b uid=jane,dc=local") - assert jane_doe.rc == 0 - assert sorted(jane_doe.stdout.strip().split("\n")) == sorted("""dn: uid=jane,dc=local +dn: uid=jane,dc=local objectClass: inetOrgPerson objectClass: simpleSecurityObject userPassword:: amFuZXBhc3N3b3Jk cn: Jane Doe sn: Doe -uid: jane""".split("\n")) +uid: jane""") + + entries = host.run("ldapsearch -H ldapi:/// -Q -LLL -Y EXTERNAL -b dc=local '(|(entrydn=uid=john,dc=local)(entrydn=uid=jane,dc=local))'") + + assert entries.rc == 0 + assert parse_ldif(entries.stdout) == expected_entries