Files @ 814be5def61d
Branch filter:

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

branko
MAR-189: Added support for Debian 11 Bullseye to xmpp_server role:

- Roll-out LDAP client configuration since Bullseye does not come with
a stock one at /etc/ldap/ldap.conf that sets the trust anchor
correctly for validating LDAP server certificates.
- Drop the backports pinning in case of Bullseye (for now let's try to
keep the Buster and Bullseye at same versions for simplicity).
- Drop installation of Python apt bindings (no longer used).
- Tests for Buster and Bullseye need to be split-up a bit due to some
differences around backports etc.
2ada86e90026
2ada86e90026
701044d4cbba
701044d4cbba
da031f975c67
701044d4cbba
d62b3adec462
da031f975c67
da031f975c67
c26fda98ff72
da031f975c67
cc7de990e9e4
cc7de990e9e4
da031f975c67
da031f975c67
e970d4afbea4
2d7abfa9286a
c26fda98ff72
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
da031f975c67
da031f975c67
da031f975c67
da031f975c67
e970d4afbea4
701044d4cbba
e970d4afbea4
701044d4cbba
da031f975c67
da031f975c67
da031f975c67
da031f975c67
701044d4cbba
c92d79571cf9
c92d79571cf9
c92d79571cf9
af834be42e8e
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
c92d79571cf9
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
87f4f8572370
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
5dab5854fcc8
87f4f8572370
5dab5854fcc8
5dab5854fcc8
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
f8f4ff29c136
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
92217994cd0c
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
d8198174bcb6
c95f61f32b67
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
c95f61f32b67
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
24033bb8b1a5
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
91e4754320e6
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
31a7f7c61740
814be5def61d
31a7f7c61740
814be5def61d
814be5def61d
31a7f7c61740
31a7f7c61740
814be5def61d
814be5def61d
31a7f7c61740
814be5def61d
814be5def61d
814be5def61d
814be5def61d
814be5def61d
31a7f7c61740
31a7f7c61740
da031f975c67
da031f975c67
da031f975c67
da031f975c67
da031f975c67
import os

import testinfra.utils.ansible_runner


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


def test_installed_packages(host):
    """
    Tests if all the necessary supporting packages have been
    installed.
    """

    assert host.package('lua-ldap').is_installed
    assert host.package('prosody-modules').is_installed
    assert host.package('prosody').is_installed


def test_prosody_user(host):
    """
    Tests if Prosody user has been set-up correctly to access TLS material.
    """

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


def test_prosody_configuration_file(host):
    """
    Tests if Prosody configuration file has correct permissions.
    """

    with host.sudo():

        config = host.file('/etc/prosody/prosody.cfg.lua')

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


def test_services(host):
    """
    Tests if services are enabled and running.
    """

    service = host.service('prosody')

    assert service.is_enabled
    assert service.is_running


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-xmpp.conf')

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


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

    fqdn = host.run('hostname -f').stdout.strip()
    dhparam_file_path = '/etc/ssl/private/%s_xmpp.dh.pem' % fqdn

    with host.sudo():
        dhparam_file = host.file(dhparam_file_path)
        assert dhparam_file.is_file
        assert dhparam_file.user == 'root'
        assert dhparam_file.group == 'prosody'
        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_prosody_tls_files(host):
    """
    Tests if Prosody TLS private key and certificage have been deployed
    correctly.
    """

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

    with host.sudo():

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

        tls_file = host.file('/etc/ssl/certs/%s_xmpp.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_xmpp.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_xmpp.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_xmpp.pem" % hostname


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

    fqdn = host.run('hostname -f').stdout.strip()

    # Use first defined domain for testing.
    domain = host.ansible.get_variables()['xmpp_domains'][0]

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

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

    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_tls_connectivity(host):
    """
    Tests if it is possible to connect to the XMPP server using
    STARTTLS/TLS.
    """

    # Use first defined domain for testing.
    domain = host.ansible.get_variables()['xmpp_domains'][0]

    starttls = host.run('echo "test" | openssl s_client -quiet -starttls xmpp -xmpphost %s -connect localhost:5222', domain)
    assert starttls.rc == 0
    assert 'jabber:client' in starttls.stdout
    assert 'not-well-formed' in starttls.stdout

    tls = host.run('echo "test" | openssl s_client -quiet -connect %s:5223', domain)
    assert tls.rc == 0
    assert 'jabber:client' in starttls.stdout
    assert 'not-well-formed' in starttls.stdout

    s2s = host.run('echo "test" | openssl s_client -quiet -starttls xmpp-server -xmpphost %s -connect localhost:5222', domain)
    assert s2s.rc == 0
    assert 'jabber:client' in s2s.stdout
    assert 'not-well-formed' in s2s.stdout


def test_prosody_configuration_validity(host):
    """
    Tests the Prosody configuration file using the 'prosodyctl check'
    command.
    """

    with host.sudo():
        check_config = host.run("prosodyctl check config")

    assert check_config.rc == 0, check_config.stdout


def test_enabled_modules(host):
    """
    Tests if correct modules have been enabled.
    """

    expected_modules = [
        "admin_adhoc",
        "announce",
        "blocklist",
        "carbons",
        "dialback",
        "disco",
        "legacyauth",
        "mam",
        "pep",
        "ping",
        "posix",
        "private",
        "register",
        "roster",
        "saslauth",
        "time",
        "tls",
        "uptime",
        "vcard",
        "version",
    ]

    with host.sudo():
        module_list_command = host.run("/usr/local/bin/list_prosody_modules.lua")

    enabled_modules = sorted(module_list_command.stdout.strip().splitlines())

    assert enabled_modules == expected_modules


def test_certificate_configuration(host):
    """
    Tests if certificates have been issued and configured correctly
    for use with Prosody. Relies on Prosody's own internal check
    command.
    """

    with host.sudo():
        check_certs = host.run("prosodyctl check certs")

    assert check_certs.rc == 0, check_certs.stdout


def test_prosody_certificate_checker_script(host):
    """
    Tests if Prosody certificate checker script has been correctly
    deployed.
    """

    with host.sudo():
        script = host.file("/usr/local/bin/check_prosody_certificate.sh")

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


def test_prosody_certificate_checker_crontab(host):
    """
    Tests if crontab entry has been deployed for running the Prosody
    certificate checker script.
    """

    crontab = host.file('/etc/cron.d/check_prosody_certificate')

    assert crontab.is_file
    assert crontab.user == 'root'
    assert crontab.group == 'root'
    assert crontab.mode == 0o644
    assert "MAILTO=root" in crontab.content_string
    assert "/usr/local/bin/check_prosody_certificate.sh" in crontab.content_string


def test_backports_repository(host):
    """
    Tests if the backports repository has been configured.
    """

    repository = host.file("/etc/apt/sources.list.d/backports.list")

    distribution_release = host.ansible("setup")["ansible_facts"]["ansible_distribution_release"]
    expected_content = "deb http://deb.debian.org/debian %s-backports main" % distribution_release

    assert repository.is_file
    assert repository.user == "root"
    assert repository.group == "root"
    assert repository.mode == 0o644
    assert repository.content_string.rstrip() == expected_content


def test_ldap_client_configuration(host):
    """
    Tests if LDAP client configuration is correctly deployed with the
    necessary trust anchor configuration.
    """

    with host.sudo():
        ldaprc = host.file("/var/lib/prosody/.ldaprc")

        assert ldaprc.is_file
        assert ldaprc.user == "root"
        assert ldaprc.group == "prosody"
        assert ldaprc.mode == 0o640
        assert "TLS_CACERT /etc/ssl/certs/ca-certificates.crt" in ldaprc.content_string


# @TODO: Tests which were not implemented due to lack of out-of-box tools:
#
# - Proxy capability.
# - MUC.
# - Server administration through XMPP.