Files @ a52f9fdabd0f
Branch filter:

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

branko
MAR-132: Added support for Debian 9 (Stretch) to web_server role:

- Introduced internal parameters for controlling differing package
names, service names, and paths for PHP FPM package.
- Added Debian 9 machines to Molecule configuration, including the
client machine.
- Restructured slightly preparaiton playbook to support both Jessie
and Stretch.
- Added custom pytest fixture for having a better way to determine
expected package names etc related to PHP.
- Created copy of private key/certificate pair used for testing of
mandatory parameters (to be used with Stretch machine).
- Fixed invalid specification for hosts on top of which the
connectivity test should be run.
- Updated a couple of task names (avoiding to reference PHP 5).
- Updated documentation.
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
57b1e111d650
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
ef201fa5ec5f
import os

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 == open('tests/data/ssh/client1.pub', 'r').read().strip()

        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 == open('tests/data/ssh/client2.pub', 'r').read().strip()


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 ( 10.31.127.1 10.31.127.3) @subchain "backup_in" {' in firewall_config.content


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 "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 "Permission denied (publickey)" in login_attempt.stderr


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


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

    # 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 ['ssh-dss', 'ssh-rsa', 'ssh-ed25519', 'ecdsa-sha2-nistp256']:

        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