diff --git a/roles/web_server/molecule/default/tests/test_mandatory.py b/roles/web_server/molecule/default/tests/test_mandatory.py index 99ad78e21f88437c10f812e3de9f1e1eb26b6ae5..3ac60b2ca2205933ed54e95b692fe3a072059512 100644 --- a/roles/web_server/molecule/default/tests/test_mandatory.py +++ b/roles/web_server/molecule/default/tests/test_mandatory.py @@ -1,68 +1,51 @@ import os -import pytest +import defusedxml.ElementTree as ElementTree import testinfra.utils.ansible_runner -from tls_ciphers import ALL_CIPHERS - - testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-mandatory') -def test_tls_version(host): +def test_tls_version_and_ciphers(host): """ - Tests if only the configured TLS protocol versions are allowed by - the server. + Tests if the correct TLS version and ciphers have been enabled. """ - old_tls_versions_disabled = host.run("echo 'Q' | openssl s_client -no_tls1_2 -connect parameters-mandatory:443") - - # Avoid false negatives by ensuring the client had actually - # established the TCP connection. - assert "CONNECTED" in old_tls_versions_disabled.stdout - assert old_tls_versions_disabled.rc != 0 - - -ENABLED_CIPHERS = [ - "DHE-RSA-AES128-GCM-SHA256", - "DHE-RSA-AES256-GCM-SHA384", - "DHE-RSA-CHACHA20-POLY1305", - "ECDHE-RSA-AES128-GCM-SHA256", - "ECDHE-RSA-AES256-GCM-SHA384", - "ECDHE-RSA-CHACHA20-POLY1305", -] + expected_tls_versions = ["TLSv1.2"] -DISABLED_CIPHERS = sorted(list(set(ALL_CIPHERS)-set(ENABLED_CIPHERS))) + 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 LDAP server, and fetch the + # results. + nmap = host.run("nmap -sV --script ssl-enum-ciphers -p 443 localhost -oX /tmp/report.xml") + assert nmap.rc == 0 + report_content = host.file('/tmp/report.xml').content_string -@pytest.mark.parametrize("cipher", ENABLED_CIPHERS) -def test_enabled_tls_ciphers(host, cipher): - """ - Tests available TLS ciphers on the server. - """ - - hostname = host.run('hostname').stdout.strip() - fqdn = hostname[:hostname.rfind('-')] + report_root = ElementTree.fromstring(report_content) - client = host.run("echo 'Q' | openssl s_client -cipher %s -connect %s:443", cipher, fqdn) - assert client.rc == 0 - assert cipher in client.stdout + tls_versions = [] + tls_ciphers = set() + for child in report_root.findall("./host/ports/port/script/table"): + tls_versions.append(child.attrib['key']) -@pytest.mark.parametrize("cipher", DISABLED_CIPHERS) -def test_disabled_tls_ciphers(host, cipher): - """ - Tests available TLS ciphers on the server. - """ + for child in report_root.findall(".//table[@key='ciphers']/table/elem[@key='name']"): + tls_ciphers.add(child.text) - hostname = host.run('hostname').stdout.strip() - fqdn = hostname[:hostname.rfind('-')] + tls_versions.sort() + tls_ciphers = sorted(list(tls_ciphers)) - client = host.run("echo 'Q' | openssl s_client -cipher %s -connect %s:443", cipher, fqdn) - assert client.rc != 0 - assert cipher not in client.stdout + assert tls_versions == expected_tls_versions + assert tls_ciphers == expected_tls_ciphers def test_https_enforcement(host):