Blame tests/test_rule_handling.py

Packit Service 39273c
import pytest
Packit Service 39273c
import mock
Packit Service 39273c
from collections import defaultdict
Packit Service 39273c
Packit Service 39273c
from pyanaconda.modules.common.constants.objects import FIREWALL, DEVICE_TREE, BOOTLOADER
Packit Service 39273c
from pyanaconda.modules.common.constants.services import NETWORK, STORAGE, USERS
Packit Service 39273c
Packit Service 39273c
try:
Packit Service 39273c
    from org_fedora_oscap import rule_handling, common
Packit Service 39273c
except ImportError as exc:
Packit Service 39273c
    pytestmark = pytest.mark.skip(
Packit Service 39273c
        "Unable to import modules, possibly due to bad version of Anaconda: {error}"
Packit Service 39273c
        .format(error=str(exc)))
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
@pytest.fixture()
Packit Service 39273c
def part_rules():
Packit Service 39273c
    rules = rule_handling.PartRules()
Packit Service 39273c
    rules.ensure_mount_point("/tmp")
Packit Service 39273c
    return rules
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
# simple tests, shouldn't raise exceptions
Packit Service 39273c
def test_part_rules_getitem(part_rules):
Packit Service 39273c
    part_rules["/tmp"]
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_part_rules_setitem(part_rules):
Packit Service 39273c
    rule = rule_handling.PartRule("/var/log")
Packit Service 39273c
    part_rules["/var/log"] = rule
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_part_rules_len(part_rules):
Packit Service 39273c
    assert len(part_rules) == 1
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_part_rules_contains(part_rules):
Packit Service 39273c
    assert "/tmp" in part_rules
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_part_rules_delitem(part_rules):
Packit Service 39273c
    del(part_rules["/tmp"])
Packit Service 39273c
    assert "/tmp" not in part_rules
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
@pytest.fixture()
Packit Service 39273c
def rule_data():
Packit Service 39273c
    return rule_handling.RuleData()
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_rule_data_artificial(rule_data):
Packit Service 39273c
    rule_data.new_rule("  part /tmp --mountoptions=nodev,noauto")
Packit Service 39273c
    rule_data.new_rule("part /var/log  ")
Packit Service 39273c
    rule_data.new_rule(" passwd   --minlen=14 ")
Packit Service 39273c
    rule_data.new_rule("package --add=iptables")
Packit Service 39273c
    rule_data.new_rule(" package --add=firewalld --remove=telnet")
Packit Service 39273c
    rule_data.new_rule("package --remove=rlogin --remove=sshd")
Packit Service 39273c
    rule_data.new_rule("bootloader --passwd")
Packit Service 39273c
Packit Service 39273c
    # both partitions should appear in rule_data._part_rules
Packit Service 39273c
    assert "/tmp" in rule_data._part_rules
Packit Service 39273c
    assert "/var/log" in rule_data._part_rules
Packit Service 39273c
Packit Service 39273c
    # mount options should be parsed
Packit Service 39273c
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
    assert "noauto" in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
Packit Service 39273c
    # no mount options for /var/log
Packit Service 39273c
    assert not rule_data._part_rules["/var/log"]._mount_options
Packit Service 39273c
Packit Service 39273c
    # minimal password length should be parsed and stored correctly
Packit Service 39273c
    assert rule_data._passwd_rules._minlen == 14
Packit Service 39273c
Packit Service 39273c
    # packages should be parsed correctly
Packit Service 39273c
    assert "iptables" in rule_data._package_rules._add_pkgs
Packit Service 39273c
    assert "firewalld" in rule_data._package_rules._add_pkgs
Packit Service 39273c
    assert "telnet" in rule_data._package_rules._remove_pkgs
Packit Service 39273c
    assert "rlogin" in rule_data._package_rules._remove_pkgs
Packit Service 39273c
    assert "sshd" in rule_data._package_rules._remove_pkgs
Packit Service 39273c
Packit Service 39273c
    # bootloader should require password
Packit Service 39273c
    assert rule_data._bootloader_rules._require_password
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_rule_data_quoted_opt_values(rule_data):
Packit Service 39273c
    rule_data.new_rule('part /tmp --mountoptions="nodev,noauto"')
Packit Service 39273c
Packit Service 39273c
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
    assert "noauto" in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
    assert '"' not in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_rule_data_real_output(rule_data):
Packit Service 39273c
    output = """
Packit Service 39273c
    part /tmp
Packit Service 39273c
Packit Service 39273c
    part /tmp --mountoptions=nodev
Packit Service 39273c
    """
Packit Service 39273c
    for line in output.splitlines():
Packit Service 39273c
        rule_data.new_rule(line)
Packit Service 39273c
Packit Service 39273c
    assert "/tmp" in rule_data._part_rules
Packit Service 39273c
    assert "nodev" in rule_data._part_rules["/tmp"]._mount_options
Packit Service 39273c
Packit Service 39273c
    # should be stripped and merged
Packit Service 39273c
    assert str(rule_data._part_rules) == "part /tmp --mountoptions=nodev"
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
@pytest.fixture()
Packit Service 39273c
def ksdata_mock():
Packit Service 39273c
    return mock.Mock()
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
@pytest.fixture()
Packit Service 39273c
def storage_mock():
Packit Service 39273c
    return mock.Mock()
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
# monkeypatch is a predefined fixture that is used to perform per-test case changes in the test env.
Packit Service 39273c
# Here, it mocks the Anaconda interface on the module level. For more info, see:
Packit Service 39273c
# https://docs.pytest.org/en/latest/monkeypatch.html#monkeypatching-mocking-modules-and-environments
Packit Service 39273c
@pytest.fixture()
Packit Service 39273c
def proxy_getter(monkeypatch):
Packit Service 39273c
    proxies = defaultdict(mock.Mock)
Packit Service 39273c
Packit Service 39273c
    def mock_get(service_name, object_path):
Packit Service 39273c
        initialize = not proxies
Packit Service 39273c
        proxy = proxies[(service_name, object_path)]
Packit Service 39273c
Packit Service 39273c
        if initialize:
Packit Service 39273c
            set_dbus_defaults()
Packit Service 39273c
Packit Service 39273c
        return proxy
Packit Service 39273c
Packit Service 39273c
    monkeypatch.setattr("pyanaconda.core.dbus.DBus.get_proxy", mock_get)
Packit Service 39273c
    return mock_get
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def set_dbus_defaults():
Packit Service 39273c
    network = NETWORK.get_proxy()
Packit Service 39273c
    network.Connected.return_value = True
Packit Service 39273c
Packit Service 39273c
    firewall = NETWORK.get_proxy(FIREWALL)
Packit Service 39273c
    firewall.EnabledServices = []
Packit Service 39273c
    firewall.DisabledServices = []
Packit Service 39273c
    firewall.EnabledPorts = []
Packit Service 39273c
    firewall.Trusts = []
Packit Service 39273c
Packit Service 39273c
    device_tree = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree.GetDeviceMountOptions.return_value = "defaults"
Packit Service 39273c
    device_tree.GetMountPoints.return_value = {}
Packit Service 39273c
Packit Service 39273c
    bootloader = STORAGE.get_proxy(BOOTLOADER)
Packit Service 39273c
    bootloader.IsPasswordSet = False
Packit Service 39273c
Packit Service 39273c
    users = USERS.get_proxy()
Packit Service 39273c
    users.IsRootPasswordSet = True
Packit Service 39273c
    users.IsRootPasswordCrypted = False
Packit Service 39273c
    users.RootPassword = "anaconda"
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_existing_part_must_exist_rules(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp",
Packit Service 39273c
        "part /",
Packit Service 39273c
    ]
Packit Service 39273c
    for rule in rules:
Packit Service 39273c
        rule_data.new_rule(rule)
Packit Service 39273c
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.GetDeviceMountOptions.return_value = "defaults"
Packit Service 39273c
    device_tree_mock.GetMountPoints.return_value = {
Packit Service 39273c
        "/tmp": "/dev/sda1",
Packit Service 39273c
        "/": "/dev/sda2",
Packit Service 39273c
    }
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # partitions exist --> no errors, warnings or additional info
Packit Service 39273c
    assert not messages
Packit Service 39273c
Packit Service 39273c
    # no additional mount options specified
Packit Service 39273c
    device_tree_mock.SetDeviceMountOptions.assert_has_calls([
Packit Service 39273c
        mock.call("/dev/sda1", "defaults"),
Packit Service 39273c
        mock.call("/dev/sda2", "defaults"),
Packit Service 39273c
    ])
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_nonexisting_part_must_exist(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp",
Packit Service 39273c
        "part /",
Packit Service 39273c
    ]
Packit Service 39273c
    for rule in rules:
Packit Service 39273c
        rule_data.new_rule(rule)
Packit Service 39273c
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.GetDeviceMountOptions.return_value = "defaults"
Packit Service 39273c
    device_tree_mock.GetMountPoints.return_value = {
Packit Service 39273c
        "/tmp": "/dev/sda1",
Packit Service 39273c
    }
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # / mount point missing --> one error
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
Packit Service 39273c
Packit Service 39273c
    # error has to mention the mount point
Packit Service 39273c
    assert "/" in messages[0].text
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def get_messages_for_partition_rules(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        rules,
Packit Service 39273c
        messages_evaluation_count=1,
Packit Service 39273c
        actual_mountpoints=("/tmp", "/"),
Packit Service 39273c
        mount_options=None,
Packit Service 39273c
        report_only=False,
Packit Service 39273c
        ):
Packit Service 39273c
Packit Service 39273c
    assert len(rules) == 2, \
Packit Service 39273c
        "We need rules for temp partition and root."
Packit Service 39273c
Packit Service 39273c
    if mount_options is None:
Packit Service 39273c
        mount_options = {
Packit Service 39273c
            "/": "defaults",
Packit Service 39273c
            "/tmp": "defaults",
Packit Service 39273c
        }
Packit Service 39273c
Packit Service 39273c
    for rule in rules:
Packit Service 39273c
        rule_data.new_rule(rule)
Packit Service 39273c
Packit Service 39273c
    # Map mount points to device names.
Packit Service 39273c
    mount_points = {}
Packit Service 39273c
Packit Service 39273c
    if "/tmp" in actual_mountpoints:
Packit Service 39273c
        mount_points["/tmp"] = "/dev/sda1"
Packit Service 39273c
Packit Service 39273c
    if "/" in actual_mountpoints:
Packit Service 39273c
        mount_points["/"] = "/dev/sda2"
Packit Service 39273c
Packit Service 39273c
    # Map device names to mount options.
Packit Service 39273c
    mount_options = {
Packit Service 39273c
        mount_points[mount_point]: mount_options[mount_point]
Packit Service 39273c
        for mount_point in actual_mountpoints
Packit Service 39273c
    }
Packit Service 39273c
Packit Service 39273c
    # Mock the device tree proxy.
Packit Service 39273c
    def get_device_mount_options(device_name):
Packit Service 39273c
        return mount_options[device_name]
Packit Service 39273c
Packit Service 39273c
    def set_device_mount_options(device_name, options):
Packit Service 39273c
        mount_options[device_name] = options
Packit Service 39273c
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.GetMountPoints.return_value = mount_points
Packit Service 39273c
    device_tree_mock.GetDeviceMountOptions.side_effect = get_device_mount_options
Packit Service 39273c
    device_tree_mock.SetDeviceMountOptions.side_effect = set_device_mount_options
Packit Service 39273c
Packit Service 39273c
    messages = []
Packit Service 39273c
    for _ in range(messages_evaluation_count):
Packit Service 39273c
        messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only)
Packit Service 39273c
Packit Service 39273c
    return messages
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def evaluation_add_mount_options(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        messages_evaluation_count):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp --mountoptions=defaults,nodev",
Packit Service 39273c
        "part / --mountoptions=noauto",
Packit Service 39273c
    ]
Packit Service 39273c
Packit Service 39273c
    messages = get_messages_for_partition_rules(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        rules, messages_evaluation_count)
Packit Service 39273c
Packit Service 39273c
    # two mount options added --> two info messages
Packit Service 39273c
    assert len(messages) == 2
Packit Service 39273c
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
Packit Service 39273c
Packit Service 39273c
    # newly added mount options should be mentioned in the messages
Packit Service 39273c
    # together with their mount points
Packit Service 39273c
    nodev_found = False
Packit Service 39273c
    noauto_found = False
Packit Service 39273c
Packit Service 39273c
    for message in messages:
Packit Service 39273c
        if "'nodev'" in message.text:
Packit Service 39273c
            assert "/tmp" in message.text
Packit Service 39273c
            nodev_found = True
Packit Service 39273c
        elif "'noauto'" in message.text:
Packit Service 39273c
            assert "/" in message.text
Packit Service 39273c
            noauto_found = True
Packit Service 39273c
Packit Service 39273c
    assert all([nodev_found, noauto_found])
Packit Service 39273c
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.SetDeviceMountOptions.assert_has_calls([
Packit Service 39273c
        mock.call("/dev/sda1", "defaults,nodev"),
Packit Service 39273c
        mock.call("/dev/sda2", "defaults,noauto"),
Packit Service 39273c
    ])
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_add_mount_options(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    evaluation_add_mount_options(rule_data, ksdata_mock, storage_mock, 1)
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_add_mount_options_no_duplicates(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    evaluation_add_mount_options(rule_data, ksdata_mock, storage_mock, 2)
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_add_mount_options_report_only(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp --mountoptions=nodev",
Packit Service 39273c
        "part / --mountoptions=noauto",
Packit Service 39273c
    ]
Packit Service 39273c
    messages = get_messages_for_partition_rules(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        rules, 1, report_only=True)
Packit Service 39273c
Packit Service 39273c
    # two mount options added --> two info messages
Packit Service 39273c
    assert len(messages) == 2
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_INFO
Packit Service 39273c
    assert messages[1].type == common.MESSAGE_TYPE_INFO
Packit Service 39273c
Packit Service 39273c
    # newly added mount options should be mentioned in the messages
Packit Service 39273c
    # together with their mount points
Packit Service 39273c
    nodev_found = False
Packit Service 39273c
    noauto_found = False
Packit Service 39273c
Packit Service 39273c
    for message in messages:
Packit Service 39273c
        if "'nodev'" in message.text:
Packit Service 39273c
            assert "/tmp" in message.text
Packit Service 39273c
            nodev_found = True
Packit Service 39273c
        elif "'noauto'" in message.text:
Packit Service 39273c
            assert "/" in message.text
Packit Service 39273c
            noauto_found = True
Packit Service 39273c
Packit Service 39273c
    assert all([nodev_found, noauto_found])
Packit Service 39273c
Packit Service 39273c
    # no changes should be made
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.SetDeviceMountOptions.assert_not_called()
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_add_mount_option_prefix(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp --mountoptions=nodev",
Packit Service 39273c
        "part / --mountoptions=noauto",
Packit Service 39273c
    ]
Packit Service 39273c
    mount_options = {
Packit Service 39273c
        "/": "defaults",
Packit Service 39273c
        "/tmp": "defaults,nodevice",
Packit Service 39273c
    }
Packit Service 39273c
    messages = get_messages_for_partition_rules(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        rules, mount_options=mount_options)
Packit Service 39273c
Packit Service 39273c
    # two mount options added (even though it is a prefix of another one)
Packit Service 39273c
    #   --> two info messages
Packit Service 39273c
    assert len(messages) == 2
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_INFO
Packit Service 39273c
    assert messages[1].type == common.MESSAGE_TYPE_INFO
Packit Service 39273c
Packit Service 39273c
    # the option should be added even though it is a prefix of another one
Packit Service 39273c
    device_tree_mock = STORAGE.get_proxy(DEVICE_TREE)
Packit Service 39273c
    device_tree_mock.SetDeviceMountOptions.assert_has_calls([
Packit Service 39273c
        mock.call("/dev/sda1", "defaults,nodevice,nodev"),
Packit Service 39273c
    ])
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_add_mount_options_nonexisting_part(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rules = [
Packit Service 39273c
        "part /tmp --mountoptions=nodev",
Packit Service 39273c
        "part / --mountoptions=noauto",
Packit Service 39273c
    ]
Packit Service 39273c
    messages = get_messages_for_partition_rules(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock,
Packit Service 39273c
        rules, actual_mountpoints=["/"])
Packit Service 39273c
Packit Service 39273c
    # one mount option added, one mount point missing (mount options
Packit Service 39273c
    # cannot be added) --> one info, one error
Packit Service 39273c
    assert len(messages) == 2
Packit Service 39273c
    assert any(message.type == common.MESSAGE_TYPE_INFO for message in messages)
Packit Service 39273c
    assert any(message.type == common.MESSAGE_TYPE_FATAL for message in messages)
Packit Service 39273c
Packit Service 39273c
    # the info message should report mount options added to the existing
Packit Service 39273c
    # mount point, the error message shoud contain the missing mount point
Packit Service 39273c
    # and not the mount option
Packit Service 39273c
    for message in messages:
Packit Service 39273c
        if message.type == common.MESSAGE_TYPE_INFO:
Packit Service 39273c
            assert "/" in message.text
Packit Service 39273c
            assert "'noauto'" in message.text
Packit Service 39273c
        elif message.type == common.MESSAGE_TYPE_FATAL:
Packit Service 39273c
            assert "/tmp" in message.text
Packit Service 39273c
            assert "'nodev'" not in message.text
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_no_passwd(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordSet = False
Packit Service 39273c
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 8, (10, 11))
Packit Service 39273c
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 10, (8, 11))
Packit Service 39273c
    evaluation_passwd_minlen_no_passwd(rule_data, ksdata_mock, storage_mock, 11, (8, 10))
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def evaluation_passwd_minlen_no_passwd(
Packit Service 39273c
        rule_data, ksdata_mock, storage_mock, min_password_length, check_against=tuple()):
Packit Service 39273c
    rule_data.new_rule("passwd --minlen={0}".format(min_password_length))
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # minimal password length required --> one warning
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
Packit Service 39273c
Packit Service 39273c
    # warning has to mention the length
Packit Service 39273c
    assert str(min_password_length) in messages[0].text
Packit Service 39273c
Packit Service 39273c
    for not_wanted in check_against:
Packit Service 39273c
        assert str(not_wanted) not in messages[0].text
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_short_passwd(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = False
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaa"
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
Packit Service 39273c
Packit Service 39273c
    # minimal password length greater than actual length --> one warning
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
Packit Service 39273c
Packit Service 39273c
    # warning has to mention the length
Packit Service 39273c
    assert "8" in messages[0].text
Packit Service 39273c
Packit Service 39273c
    # warning should mention that something is wrong with the old password
Packit Service 39273c
    assert "is" in messages[0].text
Packit Service 39273c
Packit Service 39273c
    # doing changes --> password should not be cleared
Packit Service 39273c
    assert password_proxy_mock.RootPassword == "aaaa"
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_short_passwd_report_only(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = False
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaa"
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
Packit Service 39273c
Packit Service 39273c
    # minimal password length greater than actual length --> one warning
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_FATAL
Packit Service 39273c
Packit Service 39273c
    # warning has to mention the length
Packit Service 39273c
    assert "8" in messages[0].text
Packit Service 39273c
Packit Service 39273c
    # warning should mention that something is wrong with the old password
Packit Service 39273c
    assert "is" in messages[0].text
Packit Service 39273c
Packit Service 39273c
    # doing changes --> password should not be cleared
Packit Service 39273c
    assert password_proxy_mock.RootPassword == "aaaa"
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_crypted_passwd(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = True
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaa"
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
Packit Service 39273c
Packit Service 39273c
    # minimal password length greater than actual length --> one warning
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
Packit Service 39273c
Packit Service 39273c
    # warning has to mention that the password cannot be checked
Packit Service 39273c
    assert "cannot check" in messages[0].text
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_good_passwd(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = False
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaaaaaa"
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
Packit Service 39273c
Packit Service 39273c
    # minimal password length less than actual length --> no warning
Packit Service 39273c
    assert not messages
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_passwd_minlen_report_only_not_ignored(
Packit Service 39273c
        proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = False
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaaaaaa"
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
Packit Service 39273c
Packit Service 39273c
    # Mock pw_policy returned by anaconda.pwpolicy.get_policy()
Packit Service 39273c
    pw_policy_mock = mock.Mock()
Packit Service 39273c
    pw_policy_mock.minlen = 6
Packit Service 39273c
    pw_policy_mock.strict = False
Packit Service 39273c
    ksdata_mock.anaconda.pwpolicy.get_policy.return_value = pw_policy_mock
Packit Service 39273c
Packit Service 39273c
    # call eval_rules with report_only=False
Packit Service 39273c
    # should set password minimal length to 8
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=False)
Packit Service 39273c
Packit Service 39273c
    # Password Policy changed --> no warnings
Packit Service 39273c
    assert not messages
Packit Service 39273c
    assert rule_data._passwd_rules._orig_minlen == 6
Packit Service 39273c
    assert not rule_data._passwd_rules._orig_strict
Packit Service 39273c
    assert pw_policy_mock.minlen == 8
Packit Service 39273c
    assert pw_policy_mock.strict
Packit Service 39273c
    assert rule_data._passwd_rules._minlen == 8
Packit Service 39273c
Packit Service 39273c
    # call of eval_rules with report_only=True
Packit Service 39273c
    # should not change anything
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
Packit Service 39273c
    # Password Policy stayed the same --> no warnings
Packit Service 39273c
    assert not messages
Packit Service 39273c
Packit Service 39273c
    assert rule_data._passwd_rules._orig_minlen == 6
Packit Service 39273c
    assert not rule_data._passwd_rules._orig_strict
Packit Service 39273c
    assert pw_policy_mock.minlen == 8
Packit Service 39273c
    assert pw_policy_mock.strict
Packit Service 39273c
    assert rule_data._passwd_rules._minlen == 8
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def _occurences_not_seen_in_strings(seeked, strings):
Packit Service 39273c
    found = set(seeked)
Packit Service 39273c
    for string in strings:
Packit Service 39273c
        for might_have_seen in seeked:
Packit Service 39273c
            if might_have_seen in string:
Packit Service 39273c
                found.add(string)
Packit Service 39273c
                break
Packit Service 39273c
    return set(seeked).difference(found)
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def _quoted_keywords_not_seen_in_messages(keywords, messages):
Packit Service 39273c
    return _occurences_not_seen_in_strings(
Packit Service 39273c
        {"'{}'".format(kw) for kw in keywords},
Packit Service 39273c
        [m.text for m in messages],
Packit Service 39273c
    )
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_package_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables --add=vim")
Packit Service 39273c
Packit Service 39273c
    ksdata_mock.packages.packageList = ["vim"]
Packit Service 39273c
    ksdata_mock.packages.excludedList = []
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # one info message for each (really) added/removed package
Packit Service 39273c
    assert len(messages) == 3
Packit Service 39273c
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
Packit Service 39273c
Packit Service 39273c
    # all packages should appear in the messages
Packit Service 39273c
    not_seen = _quoted_keywords_not_seen_in_messages(
Packit Service 39273c
        {"firewalld", "telnet", "iptables"},
Packit Service 39273c
        messages,
Packit Service 39273c
    )
Packit Service 39273c
Packit Service 39273c
    assert not not_seen
Packit Service 39273c
    assert set(ksdata_mock.packages.packageList) == {"firewalld", "iptables", "vim"}
Packit Service 39273c
    assert set(ksdata_mock.packages.excludedList) == {"telnet"}
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_package_rules_report_only(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables")
Packit Service 39273c
Packit Service 39273c
    ksdata_mock.packages.packageList = []
Packit Service 39273c
    ksdata_mock.packages.excludedList = []
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock, report_only=True)
Packit Service 39273c
Packit Service 39273c
    # one info message for each added/removed package
Packit Service 39273c
    assert len(messages) == 3
Packit Service 39273c
    assert all(message.type == common.MESSAGE_TYPE_INFO for message in messages)
Packit Service 39273c
Packit Service 39273c
    not_seen = _quoted_keywords_not_seen_in_messages(
Packit Service 39273c
        {"firewalld", "telnet", "iptables"},
Packit Service 39273c
        messages,
Packit Service 39273c
    )
Packit Service 39273c
Packit Service 39273c
    assert not not_seen
Packit Service 39273c
Packit Service 39273c
    # report_only --> no packages should be added or excluded
Packit Service 39273c
    assert not ksdata_mock.packages.packageList
Packit Service 39273c
    assert not ksdata_mock.packages.excludedList
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_bootloader_passwd_not_set(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    bootloader_proxy_mock = STORAGE.get_proxy(BOOTLOADER)
Packit Service 39273c
    bootloader_proxy_mock.IsPasswordSet = False
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("bootloader --passwd")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # bootloader password not set --> one warning
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert messages[0].type == common.MESSAGE_TYPE_WARNING
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_bootloader_passwd_set(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    bootloader_proxy_mock = STORAGE.get_proxy(BOOTLOADER)
Packit Service 39273c
    bootloader_proxy_mock.IsPasswordSet = True
Packit Service 39273c
Packit Service 39273c
    rule_data.new_rule("bootloader --passwd")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # bootloader password set --> no warnings
Packit Service 39273c
    assert messages == []
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_evaluation_various_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    for rule in ["part /tmp", "part /", "passwd --minlen=14",
Packit Service 39273c
                 "package --add=firewalld", ]:
Packit Service 39273c
        rule_data.new_rule(rule)
Packit Service 39273c
Packit Service 39273c
    storage_mock.mountpoints = dict()
Packit Service 39273c
    ksdata_mock.packages.packageList = []
Packit Service 39273c
    ksdata_mock.packages.excludedList = []
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # four rules, all fail --> four messages
Packit Service 39273c
    assert len(messages) == 4
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_revert_mount_options_nonexistent(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rule_data.new_rule("part /tmp --mountoptions=nodev")
Packit Service 39273c
    storage_mock.mountpoints = dict()
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # mount point doesn't exist -> one message, nothing done
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
    assert storage_mock.mountpoints == dict()
Packit Service 39273c
Packit Service 39273c
    # mount point doesn't exist -> shouldn't do anything
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
    assert storage_mock.mountpoints == dict()
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_revert_mount_options(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rule_data.new_rule("part /tmp --mountoptions=nodev")
Packit Service 39273c
    storage_mock.mountpoints = dict()
Packit Service 39273c
    storage_mock.mountpoints["/tmp"] = mock.Mock()
Packit Service 39273c
    storage_mock.mountpoints["/tmp"].format.options = "defaults"
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # mount option added --> one message
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
Packit Service 39273c
    # "nodev" option should be added
Packit Service 39273c
    assert storage_mock.mountpoints["/tmp"].format.options, "defaults == nodev"
Packit Service 39273c
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # should be reverted to the original value
Packit Service 39273c
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults"
Packit Service 39273c
Packit Service 39273c
    # another cycle of the same #
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # mount option added --> one message
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
Packit Service 39273c
    # "nodev" option should be added
Packit Service 39273c
    assert storage_mock.mountpoints["/tmp"].format.options, "defaults == nodev"
Packit Service 39273c
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # should be reverted to the original value
Packit Service 39273c
    assert storage_mock.mountpoints["/tmp"].format.options == "defaults"
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_revert_password_policy_changes(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    password_proxy_mock = USERS.get_proxy()
Packit Service 39273c
    password_proxy_mock.IsRootPasswordCrypted = False
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaa"
Packit Service 39273c
Packit Service 39273c
    # FIXME: Add password policy changes to this test. It only checks
Packit Service 39273c
    # password length right now outside of policy changes.
Packit Service 39273c
    rule_data.new_rule("passwd --minlen=8")
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # password error --> one message
Packit Service 39273c
    assert len(messages) == 1
Packit Service 39273c
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # with long enough password this time #
Packit Service 39273c
    password_proxy_mock.RootPassword = "aaaaaaaaaaaaa"
Packit Service 39273c
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # long enough password
Packit Service 39273c
    # entered --> no message
Packit Service 39273c
    assert messages == []
Packit Service 39273c
Packit Service 39273c
Packit Service 39273c
def test_revert_package_rules(proxy_getter, rule_data, ksdata_mock, storage_mock):
Packit Service 39273c
    rule_data.new_rule("package --add=firewalld --remove=telnet --add=iptables --add=vim")
Packit Service 39273c
Packit Service 39273c
    ksdata_mock.packages.packageList = ["vim"]
Packit Service 39273c
    ksdata_mock.packages.excludedList = []
Packit Service 39273c
Packit Service 39273c
    # run twice --> nothing should be different in the second run
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # one info message for each added/removed package
Packit Service 39273c
    assert len(messages) == 3
Packit Service 39273c
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # (only) added and excluded packages should have been removed from the
Packit Service 39273c
    # list
Packit Service 39273c
    assert ksdata_mock.packages.packageList == ["vim"]
Packit Service 39273c
    assert ksdata_mock.packages.excludedList == []
Packit Service 39273c
Packit Service 39273c
    # now do the same again #
Packit Service 39273c
    messages = rule_data.eval_rules(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # one info message for each added/removed package
Packit Service 39273c
    assert len(messages) == 3
Packit Service 39273c
Packit Service 39273c
    rule_data.revert_changes(ksdata_mock, storage_mock)
Packit Service 39273c
Packit Service 39273c
    # (only) added and excluded packages should have been removed from the
Packit Service 39273c
    # list
Packit Service 39273c
    assert ksdata_mock.packages.packageList == ["vim"]
Packit Service 39273c
    assert ksdata_mock.packages.excludedList == []