Files @ 17cf34f73ca6
Branch filter:

Location: majic-ansible-roles/roles/mail_server/tests/test_client2.py

branko
MAR-28: Implemented additional tests for mail_server role:

- Deploy a number of tools on clients in order to test SMTP, IMAP, and Sieve
services.
- Added one more user to LDAP directory for testing group restrictions.
- Deploy CA certificate on all testing machines for TLS validation purposes.
- Use different custom-configured cipher for mail server ciphers.
- Fixed invalid postmaster address for parameters-optional host.
- Deploy configuration files for use with Imap-CLI on client test machines.
- Updated testing of SMTP server to include checks for users that do not belong
to mail group.
- Extended some SMTP-related tests to cover both test servers.
- Some small fixes in SMTP-related tests for expected output from commands.
- Implemented tests covering Dovecot (IMAP + Sieve) functionality.
- Implemented tests for running/enabled services.
- Implemented tests for ClamAV.
- Implemented tests for firewall and connectivity.
- Implemented tests for Postfix TLS configuration.
- TODO: Tests for Sieve TLS configuration have not been written yet due to
limitation of available tools.
import re

import testinfra.utils.ansible_runner


testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    '.molecule/ansible_inventory').get_hosts('client2')


def test_open_relay(Command):
    """
    Tests if mail server behaves as open relay.
    """

    no_recipients_accepted = 24

    send = Command('swaks --suppress-data --to root@client1 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Relay access denied" in send.stdout

    send = Command('swaks --suppress-data --to root@client1 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Relay access denied" in send.stdout


def test_mail_delivery(Command):
    """
    Tests if mails can be delivered to valid accounts. Has to be run on client
    with no unauthenticated relay permissions.
    """

    no_recipients_accepted = 24

    # Valid accounts.
    send = Command('swaks --suppress-data --to john.doe@domain1 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to john.doe@domain1 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to jane.doe@domain2 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to jane.doe@domain2 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    # Invalid accounts.
    send = Command('swaks --suppress-data --to john.doe@domain2 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to john.doe@domain2 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to jane.doe@domain1 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to jane.doe@domain1 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    # Test for valid mail address that's not allowed by LDAP group membership.
    send = Command('swaks --suppress-data --to nomail@domain1 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to nomail@domain1 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    # Valid aliases.
    send = Command('swaks --suppress-data --to postmaster@domain1 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to postmaster@domain1 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to webmaster@domain2 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks --suppress-data --to webmaster@domain2 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    # Invalid aliases.
    send = Command('swaks --suppress-data --to postmaster@domain2 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to postmaster@domain2 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to webmaster@domain1 --server parameters-mandatory')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout

    send = Command('swaks --suppress-data --to webmaster@domain1 --server parameters-optional')
    assert send.rc == no_recipients_accepted
    assert "Recipient address rejected: User unknown in virtual mailbox table" in send.stdout


def test_smtp_authentication(Command):
    """
    Tests if SMTP authentication works via TLS and allows sending mails to
    anywhere.
    """

    send = Command('swaks -tls --port 587 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks -tls --port 587 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout


def test_smtp_authentication_requires_tls(Command):
    """
    Tests if SMTP authentication requires TLS.
    """

    auth_error = 28

    send = Command('swaks --port 587 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-mandatory')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr

    send = Command('swaks --port 587 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-optional')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr


def test_smtp_authentication_requires_submission_port(Command):
    """
    Tests if SMTP authentication cannot be done on regular SMTP port.
    """

    auth_error = 28

    send = Command('swaks --port 25 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-mandatory')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr

    send = Command('swaks -tls --port 25 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-mandatory')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr

    send = Command('swaks --port 25 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-optional')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr

    send = Command('swaks -tls --port 25 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-optional')
    assert send.rc == auth_error
    assert "Host did not advertise authentication" in send.stderr


def test_dovecot_inbox_separator(Command):
    """
    Tests if inbox separator has been configured correctly.
    """

    pattern_slash_separator = re.compile('WARNING:imap-cli:Ignoring "LIST" response part : \([^)]*\) "/" INBOX')
    pattern_dot_separator = re.compile('WARNING:imap-cli:Ignoring "LIST" response part : \([^)]*\) "\." INBOX')

    status = Command("imapcli status -c ~/imapcli-parameters-mandatory-john_doe.conf")
    assert pattern_slash_separator.search(status.stdout) is not None

    status = Command("imapcli status -c ~/imapcli-parameters-optional-john_doe.conf")
    assert pattern_dot_separator.search(status.stdout) is not None


def test_imap_authentication_requires_tls(Command):
    """
    Tests if IMAP authentication requires TLS.
    """

    # No TLS.
    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | nc parameters-mandatory 143")
    assert command.rc == 0
    assert "LOGINDISABLED" in command.stdout

    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | nc parameters-optional 143")
    assert command.rc == 0
    assert "LOGINDISABLED" in command.stdout

    # STARTTLS.
    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | openssl s_client -quiet -connect parameters-mandatory:143 -starttls imap")
    assert command.rc == 0
    assert "LOGINDISABLED" not in command.stdout

    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | openssl s_client -quiet -connect parameters-optional:143 -starttls imap")
    assert command.rc == 0
    assert "LOGINDISABLED" not in command.stdout

    # TLS.
    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | openssl s_client -quiet -connect parameters-mandatory:993")
    assert command.rc == 0
    assert "LOGINDISABLED" not in command.stdout

    command = Command("echo -e 'a0001 CAPABILITY\na0002 LOGOUT' | openssl s_client -quiet -connect parameters-optional:993")
    assert command.rc == 0
    assert "LOGINDISABLED" not in command.stdout


def test_sieve_authentication_requires_tls(Command):
    """
    Tests if SIEVE authentication requires TLS.
    """

    # No TLS.
    command = Command("echo 'LOGOUT' | nc parameters-mandatory 4190")
    assert command.rc == 0
    assert "PLAIN LOGIN" not in command.stdout

    command = Command("echo 'LOGOUT' | nc parameters-optional 4190")
    assert command.rc == 0
    assert "PLAIN LOGIN" not in command.stdout

    # STARTTLS
    command = Command("echo 'johnpassword' | sieve-connect -u john.doe@domain1 --password 0 --server parameters-mandatory --port 4190 --list")
    assert command.rc == 0

    command = Command("echo 'johnpassword' | sieve-connect -u john.doe@domain1 --password 0 --server parameters-optional --port 4190 --list")
    assert command.rc == 0


def test_connectivity(Command, Sudo):
    """
    Tests connectivity to the mail server (ports that should be reachable).
    """

    with Sudo():

        for server in ["parameters-mandatory",
                       "parameters-optional"]:
            for port in [25, 26, 587, 143, 993, 4190]:

                ping = Command('hping3 -S -p %d -c 1 %s' % (port, server))
                assert ping.rc == 0


def test_port_forwarding(Command, Sudo):
    """
    Tests if port forwarding is set-up correctly for submission port.
    """

    send = Command('swaks -tls --port 26 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-mandatory')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout

    send = Command('swaks -tls --port 26 --auth-user john.doe@domain1 --auth-password johnpassword --to root@client1 --server parameters-optional')
    assert send.rc == 0
    assert "Ok: queued as" in send.stdout


def test_dovecot_sieve(Command):
    """
    Tests if Sieve service is available.
    """

    # Test valid users.
    command = Command('echo johnpassword | sieve-connect --list -s parameters-mandatory -p 4190 -u john.doe@domain1 --password 0')
    assert command.rc == 0

    command = Command('echo janepassword | sieve-connect --list -s parameters-optional -p 4190 -u jane.doe@domain2 --password 0')
    assert command.rc == 0

    # Test invalid users.
    command = Command('echo johnpassword | sieve-connect --list -s parameters-mandatory -p 4190 -u john.doe@domain2 --password 0')
    assert command.rc != 0
    assert "Authentication refused by server" in command.stderr

    command = Command('echo janepassword | sieve-connect --list -s parameters-optional -p 4190 -u jane.doe@domain1 --password 0')
    assert command.rc != 0
    assert "Authentication refused by server" in command.stderr