Files @ bcad613ab0c5
Branch filter:

Location: majic-ansible-roles/roles/web_server/molecule/default/tests/test_default.py

branko
MAR-151: Added support for Debian 10 Buster to preseed role:

- Updated role reference documentaiton.
- Updated role meta information.
- Updated tests.
- Parametrise distribution release in one of the tests to cover both
servers with custom overrides being tested.
import os

import testinfra.utils.ansible_runner


import pytest
testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('parameters-*')


def test_installed_packages(host, php_info):
    """
    Tests if the required packages have been installed.
    """

    assert host.package('nginx').is_installed
    assert host.package('python-setuptools').is_installed
    assert host.package('python3-setuptools').is_installed
    assert host.package('virtualenv').is_installed
    assert host.package('virtualenvwrapper').is_installed
    assert host.package(php_info.fpm_package).is_installed


def test_nginx_user(host):
    """
    Tests if Nginx user has been set-up correctly to traverse TLS directories.
    """

    assert 'ssl-cert' in host.user('www-data').groups


def test_default_tls_configuration_removed(host):
    """
    Tests if TLS configuration has been removed from the main (default)
    configuration file.
    """

    assert 'ssl_protocols' not in host.file('/etc/nginx/nginx.conf').content_string


def test_nginx_configuration_verification_script(host):
    """
    Tests if script used for verifying Nginx configuration is deployed
    correctly.
    """

    script = host.file('/usr/local/bin/nginx_verify_site.sh')

    assert script.is_file
    assert script.user == 'root'
    assert script.group == 'root'
    assert script.mode == 0o755


def test_tls_configuration_file(host):
    """
    Tests permissions of TLS configuration file.
    """

    config = host.file('/etc/nginx/conf.d/tls.conf')

    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644


def test_default_vhost_file(host):
    """
    Tests permissions of default vhost configuration file.
    """

    config = host.file('/etc/nginx/sites-available/default')

    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o640


def test_default_website_enabled(host):
    """
    Tests if default website has been enabled.
    """

    config = host.file('/etc/nginx/sites-enabled/default')

    assert config.is_symlink
    assert config.linked_to == '/etc/nginx/sites-available/default'


def test_firewall_configuration_file(host):
    """
    Tests if firewall configuration file has been deployed correctly.
    """

    with host.sudo():

        config = host.file('/etc/ferm/conf.d/30-web.conf')

        assert config.is_file
        assert config.user == 'root'
        assert config.group == 'root'
        assert config.mode == 0o640


def test_default_debian_index_removed(host):
    """
    Tests if default HTML pages provided by debian are removed.
    """

    with host.sudo():
        assert not host.file('/var/www/html').exists


def test_default_vhost_root_directory(host):
    """
    Tests if the default vhost root directory exists.
    """

    directory = host.file('/var/www/default')

    assert directory.is_directory
    assert directory.user == 'root'
    assert directory.group == 'www-data'
    assert directory.mode == 0o750


def test_default_vhost_index_page_file(host):
    """
    Tests permissions of default vhost index page.
    """

    with host.sudo():

        page = host.file('/var/www/default/index.html')

        assert page.is_file
        assert page.user == 'root'
        assert page.group == 'www-data'
        assert page.mode == 0o640


def test_services(host, php_info):
    """
    Tests if services are enabled at boot and running.
    """

    service = host.service('nginx')
    assert service.is_enabled
    assert service.is_running

    service = host.service(php_info.fpm_service)
    assert service.is_enabled
    assert service.is_running


def test_sockets(host):
    """
    Tests if web server is listening on correct ports.
    """

    assert host.socket("tcp://80").is_listening
    assert host.socket("tcp://443").is_listening


@pytest.mark.parametrize("application_type, tmpfiles_d_path",
                         [("wsgi", "/etc/tmpfiles.d/wsgi.conf"),
                          ("php", "/etc/tmpfiles.d/php7.0-fpm.conf")])
def test_socket_directories(host, application_type, tmpfiles_d_path):
    """
    Tests if directories containing sockets for WSGI and PHP apps are created
    correctly.
    """

    socket_directory = "/run/%s" % application_type
    tmpfiles_d_content = "d /run/%s/ 0750 root www-data - -" % application_type

    directory = host.file(socket_directory)
    assert directory.is_directory
    assert directory.user == 'root'
    assert directory.group == 'www-data'
    assert directory.mode == 0o750

    config = host.file(tmpfiles_d_path)
    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644
    assert config.content_string == tmpfiles_d_content


def test_php_fpm_service_overrides(host, php_info):
    """
    Tests if overrides for PHP-FPM service are deployed correctly.
    """

    directory = host.file('/etc/systemd/system/%s.service.d' % php_info.fpm_service)
    assert directory.is_directory
    assert directory.user == 'root'
    assert directory.group == 'root'
    assert directory.mode == 0o755

    config = host.file('/etc/systemd/system/%s.service.d/umask.conf' % php_info.fpm_service)
    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644


def test_php_timezone_configuration(host, php_info):
    """
    Tests if PHP timezone configuration has been set correctly.
    """

    server_timezone = host.file("/etc/timezone").content_string.strip()

    config = host.file('%s/cli/conf.d/30-timezone.ini' % php_info.base_config_dir)
    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644

    config = host.file('%s/fpm/conf.d/30-timezone.ini' % php_info.base_config_dir)
    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644

    timezone = host.run("php --php-ini %s -r %s", "%s/cli/php.ini" % php_info.base_config_dir, "echo ini_get('date.timezone');")
    assert timezone.rc == 0
    assert timezone.stdout == server_timezone

    timezone = host.run("php --php-ini %s -r %s", "%s/fpm/php.ini" % php_info.base_config_dir, "echo ini_get('date.timezone');")
    assert timezone.rc == 0
    assert timezone.stdout == server_timezone


def test_https_server_dh_parameters_file(host):
    """
    Tests if the Diffie-Hellman parameter file has been generated
    correctly.
    """

    hostname = host.run('hostname').stdout.strip()
    dhparam_file_path = '/etc/ssl/private/%s_https.dh.pem' % hostname

    with host.sudo():
        dhparam_file = host.file(dhparam_file_path)
        assert dhparam_file.is_file
        assert dhparam_file.user == 'root'
        assert dhparam_file.group == 'root'
        assert dhparam_file.mode == 0o640

        dhparam_info = host.run("openssl dhparam -noout -text -in %s", dhparam_file_path)

        assert "DH Parameters: (2048 bit)" in dhparam_info.stdout


def test_https_server_uses_correct_dh_parameters(host):
    """
    Tests if the HTTP server uses the generated Diffie-Hellman parameter.
    """

    hostname = host.run('hostname').stdout.strip()

    with host.sudo():
        expected_dhparam = host.file('/etc/ssl/private/%s_https.dh.pem' % hostname).content_string.rstrip()

    connection = host.run("gnutls-cli --no-ca-verification --starttls-proto=https --port 443 "
                          "--priority 'NONE:+VERS-TLS1.2:+CTYPE-X509:+COMP-NULL:+SIGN-RSA-SHA384:+DHE-RSA:+SHA384:+AEAD:+AES-256-GCM' --verbose localhost")

    output = connection.stdout
    begin_marker = "-----BEGIN DH PARAMETERS-----"
    end_marker = "-----END DH PARAMETERS-----"
    used_dhparam = output[output.find(begin_marker):output.find(end_marker) + len(end_marker)]

    assert used_dhparam == expected_dhparam


def test_nginx_tls_files(host):
    """
    Tests if TLS private key and certificate have been deployed correctly.
    """

    hostname = host.run('hostname').stdout.strip()

    with host.sudo():

        tls_file = host.file('/etc/ssl/private/%s_https.key' % hostname)
        assert tls_file.is_file
        assert tls_file.user == 'root'
        assert tls_file.group == 'root'
        assert tls_file.mode == 0o640
        assert tls_file.content_string == open("tests/data/x509/server/%s_https.key.pem" % hostname, "r").read().rstrip()

        tls_file = host.file('/etc/ssl/certs/%s_https.pem' % hostname)
        assert tls_file.is_file
        assert tls_file.user == 'root'
        assert tls_file.group == 'root'
        assert tls_file.mode == 0o644
        assert tls_file.content_string == open("tests/data/x509/server/%s_https.cert.pem" % hostname, "r").read().rstrip()


def test_certificate_validity_check_configuration(host):
    """
    Tests if certificate validity check configuration file has been deployed
    correctly.
    """

    hostname = host.run('hostname').stdout.strip()

    config = host.file('/etc/check_certificate/%s_https.conf' % hostname)
    assert config.is_file
    assert config.user == 'root'
    assert config.group == 'root'
    assert config.mode == 0o644
    assert config.content_string == "/etc/ssl/certs/%s_https.pem" % hostname


def test_tls_enabled(host):
    """
    Tests if TLS has been enabled.
    """

    hostname = host.run('hostname').stdout.strip()
    fqdn = hostname[:hostname.rfind('-')]

    tls = host.run('wget -q -O - https://%s/', fqdn)
    assert tls.rc == 0


def test_https_enforcement(host):
    """
    Tests if HTTPS is being enforced.
    """

    hostname = host.run('hostname').stdout.strip()
    fqdn = hostname[:hostname.rfind('-')]

    https_enforcement = host.run('curl -I http://%s/', fqdn)

    assert https_enforcement.rc == 0
    assert 'HTTP/1.1 301 Moved Permanently' in https_enforcement.stdout
    assert 'Location: https://%s/' % fqdn in https_enforcement.stdout

    https_enforcement = host.run('curl -I https://%s/', fqdn)

    assert https_enforcement.rc == 0
    assert 'Strict-Transport-Security: max-age=31536000; includeSubDomains' in https_enforcement.stdout