Files @ fefde7a74438
Branch filter:

Location: majic-ansible-roles/roles/backup_server/molecule/default/tests/test_parameters_optional.py

branko
MAR-192: Added support for Debian 12 Bookworm to common role:

- Use slightly more memory for Debian 12 Bookworm VMs, they have a
tendency to OOM otherwise (march of progress).
- Update regex for matching the DIR_MODE confiuration in Debian 12.
- Remove NTP pacakges if ntp_pools parameter was not set.
import os

import pytest
import testinfra.utils.ansible_runner


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


def test_backup_client_users_and_groups(host):
    """
    Tests if the system groups and users for backup clients have been set-up
    correctly.
    """

    with host.sudo():

        client1_group = host.group('bak-client1_backup')
        assert client1_group.exists
        assert client1_group.gid < 1000

        client1_user = host.user('bak-client1_backup')
        assert client1_user.exists
        assert client1_user.group == 'bak-client1_backup'
        assert sorted(client1_user.groups) == sorted(['bak-client1_backup', 'backup'])
        assert client1_user.home == '/srv/backups/client1.backup'
        assert client1_user.uid < 1000
        assert client1_user.password == '!'

        client2_group = host.group('bak-client2-backup')
        assert client2_group.exists
        assert client2_group.gid == 5001

        client2_user = host.user('bak-client2-backup')
        assert client2_user.exists
        assert client2_user.group == 'bak-client2-backup'
        assert sorted(client2_user.groups) == sorted(['bak-client2-backup', 'backup'])
        assert client2_user.home == '/srv/backups/client2-backup'
        assert client2_user.uid == 5001
        assert client2_user.password == '!'


def test_backup_client_home_directories(host):
    """
    Tests if the home directory structure has been set-up correctly for the
    backup client system user.
    """

    with host.sudo():

        client1_user = host.user('bak-client1_backup')

        client1_user_home = host.file(client1_user.home)
        assert client1_user_home.is_directory
        assert client1_user_home.user == 'root'
        assert client1_user_home.group == 'bak-client1_backup'
        assert client1_user_home.mode == 0o750

        client1_user_duplicity = host.file(os.path.join(client1_user.home, 'duplicity'))
        assert client1_user_duplicity.is_directory
        assert client1_user_duplicity.user == 'bak-client1_backup'
        assert client1_user_duplicity.group == 'bak-client1_backup'
        assert client1_user_duplicity.mode == 0o770

        client1_user_ssh = host.file(os.path.join(client1_user.home, '.ssh'))
        assert client1_user_ssh.is_directory
        assert client1_user_ssh.user == 'root'
        assert client1_user_ssh.group == 'root'
        assert client1_user_ssh.mode == 0o751

        # This verifies /etc/skel was not used for setting-up home.
        assert not host.file(os.path.join(client1_user.home, '.bashrc')).exists

        client2_user = host.user('bak-client2-backup')

        client2_user_home = host.file(client2_user.home)
        assert client2_user_home.is_directory
        assert client2_user_home.user == 'root'
        assert client2_user_home.group == 'bak-client2-backup'
        assert client2_user_home.mode == 0o750

        client2_user_duplicity = host.file(os.path.join(client2_user.home, 'duplicity'))
        assert client2_user_duplicity.is_directory
        assert client2_user_duplicity.user == 'bak-client2-backup'
        assert client2_user_duplicity.group == 'bak-client2-backup'
        assert client2_user_duplicity.mode == 0o770

        client2_user_ssh = host.file(os.path.join(client2_user.home, '.ssh'))
        assert client2_user_ssh.is_directory
        assert client2_user_ssh.user == 'root'
        assert client2_user_ssh.group == 'root'
        assert client2_user_ssh.mode == 0o751

        # This verifies /etc/skel was not used for setting-up home.
        assert not host.file(os.path.join(client2_user.home, '.bashrc')).exists


def test_backup_client_authorized_keys(host):
    """
    Tests if the authorized keys for backup client system user have been set-up
    correctly.
    """

    with host.sudo():

        client1_user = host.user('bak-client1_backup')

        client1_user_authorized_keys = host.file(os.path.join(client1_user.home, '.ssh', 'authorized_keys'))
        assert client1_user_authorized_keys.is_file
        assert client1_user_authorized_keys.user == 'root'
        assert client1_user_authorized_keys.group == 'bak-client1_backup'
        assert client1_user_authorized_keys.mode == 0o640
        assert client1_user_authorized_keys.content_string == open('tests/data/ssh/client1.pub', 'r').read()

        client2_user = host.user('bak-client2-backup')

        client2_user_authorized_keys = host.file(os.path.join(client2_user.home, '.ssh', 'authorized_keys'))
        assert client2_user_authorized_keys.is_file
        assert client2_user_authorized_keys.user == 'root'
        assert client2_user_authorized_keys.group == 'bak-client2-backup'
        assert client2_user_authorized_keys.mode == 0o640
        assert client2_user_authorized_keys.content_string == open('tests/data/ssh/client2.pub', 'r').read()


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

    with host.sudo():

        firewall_config = host.file('/etc/ferm/conf.d/40-backup.conf')

        assert firewall_config.is_file
        assert firewall_config.user == 'root'
        assert firewall_config.group == 'root'
        assert firewall_config.mode == 0o640
        assert 'saddr ( 192.168.56.1 192.168.56.3) @subchain "backup_in" {' in firewall_config.content_string


@pytest.mark.usefixtures("prepare_ssh_client_private_key_permissions")
def test_regular_ssh_server_inaccessible(host):
    """
    Tests if the default SSH server is inaccessible for the backup client system
    users.
    """

    # Extract first non-IPv6 IP. Crude test, but it should work.
    remote_ip = next(a for a in host.interface("eth1").addresses if ":" not in a)
    local = host.get_host("local://")

    # Test connectivity towards regular ssh (should fail).
    login_attempt = local.run("ssh "
                              "-o PasswordAuthentication=no "
                              "-o StrictHostKeyChecking=no "
                              "-o UserKnownHostsFile=/dev/null "
                              "-i tests/data/ssh/client1 "
                              "bak-client1_backup@%s "
                              "/bin/echo sshtest" % remote_ip)
    assert login_attempt.rc != 0
    assert "bad permissions" not in login_attempt.stderr  # Avoid passing test due to client private key having wrong permissions.
    assert "Permission denied (publickey)" in login_attempt.stderr

    login_attempt = local.run("ssh "
                              "-o PasswordAuthentication=no "
                              "-o StrictHostKeyChecking=no "
                              "-o UserKnownHostsFile=/dev/null "
                              "-i tests/data/ssh/client2 "
                              "bak-client2-backup@%s "
                              "/bin/echo sshtest" % remote_ip)
    assert login_attempt.rc != 0
    assert "bad permissions" not in login_attempt.stderr  # Avoid passing test due to client private key having wrong permissions.
    assert "Permission denied (publickey)" in login_attempt.stderr


@pytest.mark.usefixtures("prepare_ssh_client_private_key_permissions")
def test_backup_ssh_service_connectivity(host):
    """
    Tests if SFTP (only) is availavble to system users used by backup clients.
    """

    # Extract first non-IPv6 IP. Crude test, but it should work.
    remote_ip = next(a for a in host.interface("eth1").addresses if ":" not in a)

    local = host.get_host("local://")

    # Test connectivity towards dedicated ssh (should be allowed, but only for sftp).
    login_attempt = local.run("ssh -p 2222 "
                              "-o PasswordAuthentication=no "
                              "-o StrictHostKeyChecking=no "
                              "-o UserKnownHostsFile=/dev/null "
                              "-i tests/data/ssh/client1 "
                              "bak-client1_backup@%s /bin/echo sshtest" % remote_ip)
    assert login_attempt.rc == 1
    assert "This service allows sftp connections only." in login_attempt.stdout

    # Test connectivity towards dedicated ssh (should be allowed, but only for sftp).
    login_attempt = local.run("ssh -p 2222 "
                              "-o PasswordAuthentication=no "
                              "-o StrictHostKeyChecking=no "
                              "-o UserKnownHostsFile=/dev/null "
                              "-i tests/data/ssh/client2 "
                              "bak-client2-backup@%s /bin/echo sshtest" % remote_ip)
    assert login_attempt.rc == 1
    assert "This service allows sftp connections only." in login_attempt.stdout


@pytest.mark.usefixtures("prepare_ssh_client_private_key_permissions")
def test_backup_ssh_service_key_fingerprints(host):
    """
    Tests fingerprints of backup SSH server in order to ensure correct keys are
    in use.
    """

    key_types = ['ssh-rsa', 'ssh-ed25519', 'ecdsa-sha2-nistp256']

    # Extract first non-IPv6 IP. Crude test, but it should work.
    remote_ip = next(a for a in host.interface("eth1").addresses if ":" not in a)

    local = host.get_host("local://")

    for key_type in key_types:

        login_attempt = local.run("ssh -p 2222 "
                                  "-o PasswordAuthentication=no "
                                  "-o StrictHostKeyChecking=yes "
                                  "-o UserKnownHostsFile=tests/data/ssh/known_hosts "
                                  "-i tests/data/ssh/client1 "
                                  "-o HostKeyAlgorithms=%s "
                                  "bak-client1_backup@%s /bin/echo sshtest" % (key_type, remote_ip))
        assert login_attempt.rc == 1
        assert "This service allows sftp connections only." in login_attempt.stdout