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').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 def test_dependent_packages_not_installed_from_prosody_repository(host): """ Tests if no dependent packages have been installed from the Prosody project repository. This tests exists primarily to check if the Ansible code will switch over correctly to using the stock Debian packages instead, since upstream has a tendency to drop repositories for old Debian releases (they do not support Debian LTS releases). """ # Retrieve list of all packages except Prosody itself, and check # if any of them mention prosody in the version string. packages = host.run("dpkg-query --show --showformat '${db:Status-Status} ${Package} ${Version}\n' |" "grep '^installed' | grep -v '^installed prosody' | grep prosody").stdout assert packages == "" def test_prosody_package_not_installed_from_prosody_repository(host): """ Tests if Prosody package itself has not been installed from the project repository" This tests exists primarily to check if the Ansible code will switch over correctly to using the stock Debian packages instead, since upstream has a tendency to drop repositories for old Debian releases (they do not support Debian LTS releases). """ # Extract name of package providing Prosody XMPP server. package_name = host.run(" dpkg-query --show --showformat '${db:Status-Status} ${Package}: ${Provides} \n'" "| grep '^installed' | grep ': .*xmpp-server'" "| sed -e 's/installed //;s/:.*//'").stdout.strip() assert package_name != "", "Failed to extract name of package providing Prosody." package_info = host.run("dpkg-query --show --showformat 'Package: ${Package}\nVersion: ${Version}\nMaintainer: ${Maintainer}\n' %s", package_name) assert package_info.rc == 0, "Failed to retrieve information about package: %s " % package_name assert "nightly" not in package_info.stdout assert "Matthew James Wild" not in package_info.stdout @pytest.mark.parametrize("apt_key", [ "107D 65A0 A148 C237 FDF0 0AB4 7393 D7E6 74D9 DBB5", "44AB 6DD0 6DA4 6979 CFAF 997F 9B1B 8278 6C8F 28BA" ]) def test_prosody_apt_key_is_absent(host, apt_key): """ Tests if Prosody repository signing key has been removed. """ keys = host.run("apt-key adv --fingerprint --fingerprint prosody") assert apt_key not in keys.stdout def test_prosody_repository_is_absent(host): """ Tests if Prosody repository is absent. """ assert not host.file("/etc/apt/sources.list.d/packages_prosody_im_debian.list").exists def test_prosody_modules_directory_is_absent(host): """ Tests if directory for storing deprecated Prosody modules has been correctly removed. """ directory = host.file('/usr/local/lib/prosody/') assert not directory.exists