From 895e9bd5a83b8c7bb78942b5d039fa90050871b5 2023-08-14 00:30:27 From: Branko Majic Date: 2023-08-14 00:30:27 Subject: [PATCH] MAR-181: Add VM for testing deprecations in xmpp_server role. --- diff --git a/roles/xmpp_server/molecule/default/group_vars/deprecated.yml b/roles/xmpp_server/molecule/default/group_vars/deprecated.yml new file mode 100644 index 0000000000000000000000000000000000000000..d823799e1d34a15f792e09136ffbe2708b75fce7 --- /dev/null +++ b/roles/xmpp_server/molecule/default/group_vars/deprecated.yml @@ -0,0 +1,15 @@ +--- + +xmpp_administrators: + - eve.doe@domain4 +xmpp_domains: + - domain4 +xmpp_ldap_base_dn: dc=local +xmpp_ldap_password: prosodypassword +xmpp_ldap_server: ldap-server +xmpp_tls_certificate: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_xmpp.cert.pem') }}" +xmpp_tls_key: "{{ lookup('file', 'tests/data/x509/server/{{ inventory_hostname }}_xmpp.key.pem') }}" + +# common +ca_certificates: + testca: "{{ lookup('file', 'tests/data/x509/ca/level1.cert.pem') }}" diff --git a/roles/xmpp_server/molecule/default/molecule.yml b/roles/xmpp_server/molecule/default/molecule.yml index a92a818d2eb2769293e174814c5a77dd2ebbbf0f..452cfd2efe040f18ef705df23b318632e5540e50 100644 --- a/roles/xmpp_server/molecule/default/molecule.yml +++ b/roles/xmpp_server/molecule/default/molecule.yml @@ -63,6 +63,19 @@ platforms: network_name: private_network type: static + - name: deprecated-buster64 + groups: + - deprecated + - buster + box: debian/contrib-buster64 + memory: 512 + cpus: 1 + interfaces: + - auto_config: true + ip: 192.168.56.32 + network_name: private_network + type: static + provisioner: name: ansible playbooks: diff --git a/roles/xmpp_server/molecule/default/playbook.yml b/roles/xmpp_server/molecule/default/playbook.yml index 28027f6e59874d5ac59044ec106661d2b9e80c76..6a054690180ae917260e163c1483db00ed9725ef 100644 --- a/roles/xmpp_server/molecule/default/playbook.yml +++ b/roles/xmpp_server/molecule/default/playbook.yml @@ -1,6 +1,6 @@ --- -- hosts: parameters-mandatory,parameters-optional +- hosts: parameters-mandatory,parameters-optional,deprecated become: true roles: - xmpp_server diff --git a/roles/xmpp_server/molecule/default/prepare.yml b/roles/xmpp_server/molecule/default/prepare.yml index f291cbe450ba85cd7254ff18900e4f782b5a6f7a..38751d7f343b315c92c9d4f03c91bb54ad337c47 100644 --- a/roles/xmpp_server/molecule/default/prepare.yml +++ b/roles/xmpp_server/molecule/default/prepare.yml @@ -37,6 +37,12 @@ - domain3 - proxy.domain3 - conference.domain3 + - name: deprecated-buster64_xmpp + fqdn: + - deprecated + - domain4 + - proxy.domain4 + - conference.domain4 - name: Set-up link to generated X.509 material file: @@ -93,6 +99,7 @@ 192.168.56.20: "client-buster" 192.168.56.30: "parameters-mandatory domain1 proxy.domain1 conference.domain1" 192.168.56.31: "parameters-optional domain2 proxy.domain2 conference.domain2 domain3 proxy.domain3 conference.domain3" + 192.168.56.32: "deprecated domain4 proxy.domain4 conference.domain4" - name: Enable TLSv1.0+ in global OpenSSL configuration file in order to be able to test the xmpp_server_tls_protocol parameter lineinfile: @@ -104,15 +111,11 @@ mode: 0644 state: present - # @WORKAROUND: BEGIN - Prosody repository override - + # @WORKAROUND: Prosody repository override + # # Prosody project has killed off Debian Buster repositories. Trick # the system to install packages from custom repository location # instead. - - # Prosody project has killed off Debian Buster repositories. The - # custom repository used to install the packages has been signed - # by different key. - name: Override server IP for Prosody repository via hosts file lineinfile: path: /etc/hosts @@ -122,12 +125,15 @@ group: root mode: 0644 state: present + tags: + - workaround:prosody_repository_override - name: Add workaround Prosody repository signing key apt_key: data: "{{ lookup('file', 'workaround_prosody_repository_signing_key.asc') }}" state: present - # @WORKAROUND: END - Prosody repository override + tags: + - workaround:prosody_repository_override - hosts: clients become: true @@ -197,6 +203,11 @@ server: domain1 security: tls nickname: noxmpp + - jid: eve.doe@domain4 + password: evepassword + server: domain4 + security: tls + nickname: eve.doe handlers: @@ -263,6 +274,17 @@ sn: XMPP mail: noxmpp@domain1 + - dn: uid=eve,ou=people,dc=local + objectClass: + - inetOrgPerson + - simpleSecurityObject + attributes: + userPassword: evepassword + uid: eve + cn: Eve Doe + sn: Doe + mail: eve.doe@domain4 + - name: Add test accounts to correct group ldap_attr: dn: "cn=xmpp,ou=groups,dc=local" @@ -272,8 +294,9 @@ - uid=john,ou=people,dc=local - uid=jane,ou=people,dc=local - uid=mick,ou=people,dc=local + - uid=eve,ou=people,dc=local -- hosts: parameters-mandatory,parameters-optional +- hosts: parameters-mandatory,parameters-optional,deprecated become: true tasks: diff --git a/roles/xmpp_server/molecule/default/tests/test_client.py b/roles/xmpp_server/molecule/default/tests/test_client.py index c2b8cc3151d5b2edcd19c498d56bceeee790f0d0..d6319f243280118931d51cac735699645547b5da 100644 --- a/roles/xmpp_server/molecule/default/tests/test_client.py +++ b/roles/xmpp_server/molecule/default/tests/test_client.py @@ -28,6 +28,7 @@ def test_connectivity(host): @pytest.mark.parametrize("username, password, domain", [ ["john.doe", "johnpassword", "domain1"], ["jane.doe", "janepassword", "domain2"], + ["eve.doe", "evepassword", "domain4"], ]) def test_tls(host, username, password, domain): """ @@ -46,6 +47,7 @@ def test_tls(host, username, password, domain): @pytest.mark.parametrize("username, password, domain", [ ["john.doe", "johnpassword", "domain1"], ["jane.doe", "janepassword", "domain2"], + ["eve.doe", "evepassword", "domain4"], ]) def test_authentication_requires_tls(host, username, password, domain): """ @@ -61,6 +63,7 @@ def test_authentication_requires_tls(host, username, password, domain): ["john.doe", "johnpassword", "domain1"], ["jane.doe", "janepassword", "domain2"], ["mick.doe", "mickpassword", "domain3"], + ["eve.doe", "evepassword", "domain4"], ]) def test_authentication(host, username, password, domain): """ @@ -79,6 +82,7 @@ def test_authentication(host, username, password, domain): @pytest.mark.parametrize("target_username, target_domain", [ ["john.doe", "domain1"], ["jane.doe", "domain2"], + ["eve.doe", "domain4"], ]) def test_unauthorized_users_rejected(host, target_username, target_domain): """ diff --git a/roles/xmpp_server/molecule/default/tests/test_default.py b/roles/xmpp_server/molecule/default/tests/test_default.py index 6a982804f27f5d827661cfee9ab957bb2b0052f0..426c42720f70fa007628bf06b217be0fa95ff7c4 100644 --- a/roles/xmpp_server/molecule/default/tests/test_default.py +++ b/roles/xmpp_server/molecule/default/tests/test_default.py @@ -6,6 +6,9 @@ import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*') +testinfra_hosts += testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('deprecated') + def test_supporting_packages_installed(host): """ diff --git a/roles/xmpp_server/molecule/default/tests/test_default_buster.py b/roles/xmpp_server/molecule/default/tests/test_default_buster.py index d9ddbd345bbfaf400f1de2c2748d52ddf4fd27ab..8a4c4cb39e476cd6facf0ed76484acc9a8b31dc1 100644 --- a/roles/xmpp_server/molecule/default/tests/test_default_buster.py +++ b/roles/xmpp_server/molecule/default/tests/test_default_buster.py @@ -6,6 +6,9 @@ import testinfra.utils.ansible_runner testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*-buster64') +testinfra_hosts += testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('deprecated-buster64') + def test_lua_ldap_pin_and_version(host): """ diff --git a/roles/xmpp_server/molecule/default/tests/test_deprecated.py b/roles/xmpp_server/molecule/default/tests/test_deprecated.py new file mode 100644 index 0000000000000000000000000000000000000000..c86acd24b23351312453a91625cbf8e90df57315 --- /dev/null +++ b/roles/xmpp_server/molecule/default/tests/test_deprecated.py @@ -0,0 +1,91 @@ +import os + +import defusedxml.ElementTree as ElementTree + +import pytest + +import testinfra.utils.ansible_runner + + +testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( + os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('deprecated') + + +def test_prosody_configuration_file_content(host): + """ + Tests if Prosody configuration file has correct content. + """ + + hostname = host.run('hostname').stdout.strip() + + with host.sudo(): + + config = host.file('/etc/prosody/prosody.cfg.lua') + + assert "admins = { \"eve.doe@domain4\", }" in config.content_string + assert "key = \"/etc/ssl/private/%s_xmpp.key\";" % hostname in config.content_string + assert "certificate = \"/etc/ssl/certs/%s_xmpp.pem\";" % hostname in config.content_string + assert "ldap_server = \"ldap-server\"" in config.content_string + assert "ldap_rootdn = \"cn=prosody,ou=services,dc=local\"" in config.content_string + assert "ldap_password = \"prosodypassword\"" in config.content_string + assert "ldap_filter = \"(&(mail=$user@$host)(memberOf=cn=xmpp,ou=groups,dc=local))\"" in config.content_string + assert "ldap_base = \"ou=people,dc=local\"" in config.content_string + assert "archive_expires_after = \"never\"" in config.content_string + + assert """VirtualHost "domain4" +Component "conference.domain4" "muc" + restrict_room_creation = "local" +Component "proxy.domain4" "proxy65" + proxy65_acl = { "domain4" }""" in config.content_string + + +def test_correct_prosody_package_installed(host): + """ + Tests if correct Prosody package has been installed. + """ + + assert host.package('prosody-0.11').is_installed + + +@pytest.mark.parametrize("port", [ + 5222, + 5223 +]) +def test_xmpp_c2s_tls_version_and_ciphers(host, port): + """ + Tests if the correct TLS version and ciphers have been enabled for + XMPP C2S ports. + """ + + expected_tls_versions = ["TLSv1.2"] + + expected_tls_ciphers = [ + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", + ] + + # Run the nmap scanner against the server, and fetch the results. + nmap = host.run("nmap -sV --script ssl-enum-ciphers -p %s domain4 -oX /tmp/report.xml", str(port)) + assert nmap.rc == 0 + report_content = host.file('/tmp/report.xml').content_string + + report_root = ElementTree.fromstring(report_content) + + tls_versions = [] + tls_ciphers = set() + + for child in report_root.findall("./host/ports/port/script[@id='ssl-enum-ciphers']/table"): + tls_versions.append(child.attrib['key']) + + for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"): + tls_ciphers.add(child.text) + + tls_versions.sort() + tls_ciphers = sorted(list(tls_ciphers)) + + assert tls_versions == expected_tls_versions + assert tls_ciphers == expected_tls_ciphers