diff --git a/roles/web_server/molecule/default/tests/test_optional.py b/roles/web_server/molecule/default/tests/test_optional.py index c71cd59753f5335e0d21d8fe43465176b5c18956..624bd021caab3796b544a83e11da3613bc98f890 100644 --- a/roles/web_server/molecule/default/tests/test_optional.py +++ b/roles/web_server/molecule/default/tests/test_optional.py @@ -1,83 +1,54 @@ 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-optional') -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_1 -no_tls1_2 -connect parameters-optional:443") - tls1_1_enabled = host.run("echo 'Q' | openssl s_client -tls1_1 -connect parameters-optional:443") - tls1_2_enabled = host.run("echo 'Q' | openssl s_client -tls1_2 -connect parameters-optional: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 - - # Avoid false negatives by ensuring the client had actually - # established the TCP connection. - assert "CONNECTED" in tls1_1_enabled.stdout - assert tls1_1_enabled.rc == 0 - - # Avoid false negatives by ensuring the client had actually - # established the TCP connection. - assert "CONNECTED" in tls1_2_enabled.stdout - assert tls1_2_enabled.rc == 0 - + expected_tls_versions = ["TLSv1.1", "TLSv1.2"] -ENABLED_CIPHERS = [ - "DHE-RSA-AES128-GCM-SHA256", - "DHE-RSA-AES128-SHA256", - "DHE-RSA-AES256-GCM-SHA384", - "DHE-RSA-AES256-SHA256", - "ECDHE-RSA-AES128-GCM-SHA256", - "ECDHE-RSA-AES128-SHA", - "ECDHE-RSA-AES128-SHA256", - "ECDHE-RSA-AES256-GCM-SHA384", - "ECDHE-RSA-AES256-SHA384", -] + expected_tls_ciphers = [ + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", + "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + ] -DISABLED_CIPHERS = sorted(list(set(ALL_CIPHERS)-set(ENABLED_CIPHERS))) + # 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 + report_root = ElementTree.fromstring(report_content) -@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('-')] + tls_versions = [] + tls_ciphers = set() - client = host.run("echo 'Q' | openssl s_client -cipher %s -connect %s:443", cipher, fqdn) - assert client.rc == 0 - assert cipher in client.stdout + for child in report_root.findall("./host/ports/port/script/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) -@pytest.mark.parametrize("cipher", DISABLED_CIPHERS) -def test_disabled_tls_ciphers(host, cipher): - """ - Tests available TLS ciphers on the server. - """ - - 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):