Ejemplo n.º 1
0
def test_commands(monkeypatch):
    """
    .
    """

    # pylint: disable=unused-argument
    @counter_wrapper
    def rule_commands(self) -> List[str]:
        commands = []
        if rule_commands.counter == 1:
            commands = ["rule1-command1", "rule1-command2"]
        else:
            commands = ["rule2-command1", "rule2-command2", "rule2-command3"]

        return commands

    monkeypatch.setattr(NATRule, "commands", rule_commands)

    nat_properties = {
        "rules": [NATRule(10, "."), NATRule(20, ".")],
    }
    nat = NAT(".", **nat_properties)
    assert nat.commands() == [
        "rule1-command1",
        "rule1-command2",
        "rule2-command1",
        "rule2-command2",
        "rule2-command3",
    ], "Commands generated correctly"
Ejemplo n.º 2
0
def test_masquerade():
    """
    Masquerade differs from normal rules, check that separately
    """
    properties = {
        "type": "masquerade",
        "protocol": "all",
        "outbound-interface": "eth0"
    }
    rule = NATRule(1000, ".", **properties)
    assert rule.validate(), "Masquerade rule valid"
Ejemplo n.º 3
0
def test_get_next_number():
    """
    .
    """
    properties = {
        "rules": [NATRule(11, "."), NATRule(100, ".")],
        "auto-increment": 100,
    }
    nat = NAT(".", **properties)
    assert getattr(nat, "auto-increment") == 100, "Auto increment overridden"
    assert nat.next_rule_number() == 200, "Next rule number correct"

    nat.add_rule({"number": 200, "config_path": "."})
    assert nat.next_rule_number() == 300, "Next rule number updated after adding rule"
Ejemplo n.º 4
0
def test_group_address_commands():
    """
    .
    """
    rule_properties = {
        "description": "rule",
        "source": {
            "address": "a-group",
            "port": "web-ports"
        },
        "destination": {
            "address": "the.whole.internet",
            "port": "any"
        },
    }
    commands = NATRule(10, ".", **rule_properties).commands()
    rule_base = "service nat rule 10 "

    assert commands == [
        rule_base + 'description "rule"',
        rule_base + "source group address-group a-group",
        rule_base + "source group port-group web-ports",
        rule_base + "destination group address-group the.whole.internet",
        rule_base + "destination group port-group any",
    ], "Rule commands correct"
Ejemplo n.º 5
0
def test_non_group_address_commands():
    """
    .
    """
    rule_properties = {
        "description": "rule",
        "source": {
            "address": "10.10.10.10",
            "port": 8080
        },
        "destination": {
            "address": "8.8.8.8",
            "port": "443"
        },
        "inside-address": {
            "address": "192.168.0.2",
            "port": 80
        },
    }
    commands = NATRule(10, ".", **rule_properties).commands()
    rule_base = "service nat rule 10 "

    assert commands == [
        rule_base + 'description "rule"',
        rule_base + "source address 10.10.10.10",
        rule_base + "source port 8080",
        rule_base + "destination address 8.8.8.8",
        rule_base + "destination port 443",
        rule_base + "inside-address address 192.168.0.2",
        rule_base + "inside-address port 80",
    ], "Rule commands correct"
Ejemplo n.º 6
0
def test_consistency():
    """
    .
    """
    nat = NAT(
        ".",
        rules=[
            NATRule(10, "."),
            NATRule(10, "."),
            NATRule(20, "."),
            NATRule(20, "."),
            NATRule(30, "."),
        ],
    )

    assert not nat.is_consistent(), "Not consistent"
    assert nat.validation_errors() == ["NAT has duplicate rules: 10, 20"]
Ejemplo n.º 7
0
def test_validate(monkeypatch):
    """
    .
    """

    # pylint: disable=unused-argument
    @counter_wrapper
    def fake_validate(self):
        """
        .
        """
        return True

    monkeypatch.setattr(NATRule, "validate", fake_validate)

    nat = NAT(".", rules=[NATRule(1, "."), NATRule(2, ".")],)
    assert nat.validate(), "NAT is valid"
    assert fake_validate.counter == 2, "Validation called for each rule"

    monkeypatch.setattr(NATRule, "validate", lambda self: False)
    assert not nat.validate(), "Rule validation fails"
Ejemplo n.º 8
0
def test_validation_failures(monkeypatch):
    """
    .
    """

    def fake_validation_errors(self) -> List[str]:
        """
        .
        """
        return ["problem"] if self.number == 10 else ["bad", "wrong"]

    monkeypatch.setattr(NATRule, "validation_errors", fake_validation_errors)
    monkeypatch.setattr(NAT, "validation_errors", lambda self: ["an error"])

    nat = NAT(".", rules=[NATRule(10, "."), NATRule(20, ".")],)
    assert nat.validation_failures() == [
        "an error",
        "problem",
        "bad",
        "wrong",
    ], "Validation failures are correct"
Ejemplo n.º 9
0
def test_non_address_commands():
    """
    .
    """
    rule_properties = {
        "description": "Its a rule",
        "log": "disable",
        "protocol": "tcp",
        "type": "source",
        "inbound-interface": "eth1.10",
        "outbound-interface": "eth0",
    }
    commands = NATRule(10, ".", **rule_properties).commands()

    rule_base = "service nat rule 10 "
    assert commands == [
        rule_base + "description 'Its a rule'",
        rule_base + "log disable",
        rule_base + "protocol tcp",
        rule_base + "type source",
        rule_base + "inbound-interface eth1.10",
        rule_base + "outbound-interface eth0",
    ], "Rule commands correct"
Ejemplo n.º 10
0
def test_add_firewall_rules():
    """
    .
    """
    host_properties = {
        "address-groups": ["devices"],
        "forward-ports": [
            80,
            "443",
            "server-ports",
            {"8080": 80},
            {4443: 443},
            {222: "22"},
        ],
        "hairpin-ports": [
            {
                "connection": {"destination": {"address": "8.8.8.8", "port": 53}},
                "interface": "eth1.10",
            },
            {
                "connection": {"destination": {"port": "server-ports"}},
                "description": "Hairpin server ports back to host",
                "interface": "eth0",
            },
        ],
        "connections": [
            {
                "allow": True,
                "rule": 20,
                "log": False,
                "description": "A rule",
                "source": {"address": "192.168.0.0/24",},
                "destination": {"port": "printer-ports"},
            },
            {
                "allow": False,
                "log": True,
                "description": "A rule",
                "source": {"address": "bad-things",},
                "destination": {"address": "devices", "port": 22},
            },
            {
                "allow": True,
                "description": "A rule",
                "source": {"address": "devices",},
                "destination": {"port": "allowed-ports"},
            },
            {
                "allow": False,
                "description": "A rule",
                "log": True,
                "source": {"address": "devices",},
                "destination": {"port": "blocked-ports"},
            },
            {
                "allow": True,
                "description": "A rule",
                "log": False,
                "source": {"port": "allowed-ports",},
                "destination": {"address": "devices"},
            },
        ],
    }

    host = Host(
        "host1",
        Network(
            "network", NAT("."), ".", "192.168.0.0/24", **{"interface-name": "eth0"}
        ),
        ".",
        "192.168.0.100",
        **host_properties
    )

    firewall_in = host.network.firewalls_by_direction["in"]
    firewall_out = host.network.firewalls_by_direction["out"]

    rule_20 = {
        "number": 20,
        "firewall_name": "network-IN",
        "config_path": ".",
        "action": "accept",
        "protocol": "tcp_udp",
        "log": "disable",
        "description": "A rule",
        "source": {"address": "192.168.0.0/24"},
        "destination": {"port": "printer-ports"},
    }

    rule_10 = copy.deepcopy(rule_20)
    rule_10["number"] = 10
    rule_10["source"]["address"] = "devices"
    rule_10["destination"]["port"] = "allowed-ports"

    rule_30 = copy.deepcopy(rule_10)
    rule_30["number"] = 30
    rule_30["action"] = "drop"
    rule_30["log"] = "enable"
    rule_30["destination"]["port"] = "blocked-ports"

    assert firewall_in.rules == [
        Rule(**rule_20),
        Rule(**rule_10),
        Rule(**rule_30),
    ], "Rules created for in firewall correctly"

    rule_10["action"] = "drop"
    rule_10["source"]["address"] = "bad-things"
    rule_10["destination"]["address"] = "devices"
    rule_10["destination"]["port"] = 22
    rule_10["log"] = "enable"

    rule_20 = copy.deepcopy(rule_10)
    rule_20["number"] = 20
    rule_20["action"] = "accept"
    rule_20["log"] = "disable"
    rule_20["source"] = {"port": "allowed-ports"}
    rule_20["destination"] = {"address": "devices"}

    assert firewall_out.rules == [
        Rule(**rule_10),
        Rule(**rule_20),
    ], "Rules created for out firewall correctly"

    base_rule_properties = {
        "number": 10,
        "description": "Forward port 80 to host1",
        "config_path": ".",
        "type": "destination",
        "protocol": "tcp_udp",
        "inbound-interface": "eth0",
        "inside-address": {"address": "192.168.0.100"},
        "destination": {"port": 80},
    }

    ssl_rule = copy.deepcopy(base_rule_properties)
    ssl_rule["number"] = 20
    ssl_rule["destination"]["port"] = "443"
    ssl_rule["description"] = ssl_rule["description"].replace("80", "443")

    server_rule = copy.deepcopy(base_rule_properties)
    server_rule["number"] = 30
    server_rule["destination"]["port"] = "server-ports"
    server_rule["description"] = server_rule["description"].replace(
        "80", "server-ports"
    )

    str_translate_rule = copy.deepcopy(base_rule_properties)
    str_translate_rule["number"] = 40
    str_translate_rule["destination"]["port"] = "8080"
    str_translate_rule["inside-address"]["port"] = 80
    str_translate_rule["description"] = str_translate_rule["description"].replace(
        "80", "8080"
    )

    int_translate_rule = copy.deepcopy(base_rule_properties)
    int_translate_rule["number"] = 50
    int_translate_rule["destination"]["port"] = 4443
    int_translate_rule["inside-address"]["port"] = 443
    int_translate_rule["description"] = int_translate_rule["description"].replace(
        "80", "4443"
    )

    other_translate_rule = copy.deepcopy(base_rule_properties)
    other_translate_rule["number"] = 60
    other_translate_rule["destination"]["port"] = 222
    other_translate_rule["inside-address"]["port"] = "22"
    other_translate_rule["description"] = other_translate_rule["description"].replace(
        "80", "222"
    )

    hairpin_rule = {
        "number": 70,
        "description": "",
        "config_path": ".",
        "type": "destination",
        "protocol": "tcp_udp",
        "inside-address": {"address": "192.168.0.100"},
        "destination": {"address": "8.8.8.8", "port": 53},
        "inbound-interface": "eth1.10",
    }

    hairpin_rule_2 = copy.deepcopy(hairpin_rule)
    hairpin_rule_2["number"] = 80
    hairpin_rule_2["description"] = "Hairpin server ports back to host"
    hairpin_rule_2["destination"] = {
        "address": "external-addresses",
        "port": "server-ports",
    }
    hairpin_rule_2["inbound-interface"] = "eth0"

    assert host.network.nat.rules == [
        NATRule(**base_rule_properties),
        NATRule(**ssl_rule),
        NATRule(**server_rule),
        NATRule(**str_translate_rule),
        NATRule(**int_translate_rule),
        NATRule(**other_translate_rule),
        NATRule(**hairpin_rule),
        NATRule(**hairpin_rule_2),
    ], "NAT rules created"
Ejemplo n.º 11
0
def test_validate(monkeypatch):
    """
    .
    """

    # pylint: disable=unused-argument
    @counter_wrapper
    def fake_validate_false(self) -> bool:
        """
        .
        """
        return False

    @counter_wrapper
    def fake_validate_true(self) -> bool:
        """
        .
        """
        return True

    monkeypatch.setattr(
        secondary_configs,
        "get_port_groups",
        lambda config_path: [PortGroup("group1"),
                             PortGroup("group2")],
    )

    monkeypatch.setattr(Validatable, "validate", fake_validate_false)
    rule = NATRule(10, ".")
    assert not rule.validate(), "Validation fails if parent fails"
    assert fake_validate_false.counter == 1, "Parent validation called"

    monkeypatch.setattr(Validatable, "validate", fake_validate_true)
    rule = NATRule(10, ".")
    assert not rule.validate(), "Validation fails without inside address"
    assert fake_validate_true.counter == 1, "Parent validation called"
    assert rule.validation_errors() == ["NAT rule 10 does not have type"
                                        ], "Validation errors set"

    properties = {
        "source": {
            "port": "group1"
        },
        "destination": {
            "port": "group2"
        },
    }
    rule = NATRule(10, ".", **properties)

    assert not rule.validate(), "Missing type invalid"
    assert rule.validation_errors() == ["NAT rule 10 does not have type"
                                        ], "Errors set"

    properties["type"] = "source"
    rule = NATRule(10, ".", **properties)
    assert not rule.validate(), "Missing type invalid"
    assert rule.validation_errors() == [
        "NAT rule 10 does not have inside address"
    ], "Errors set"

    properties["inside-address"] = ({"address": "192.168.0.2"}, )

    rule = NATRule(10, ".", **properties)
    assert rule.validate(), "Rule is valid if groups are valid"
    rule = NATRule(10, ".", **properties)

    properties["source"]["port"] = "group3"
    properties["destination"]["port"] = "group4"
    assert not rule.validate(), "Rule is invalid with nonexistent groups"
    assert rule.validation_errors() == [
        "NAT rule 10 has nonexistent source port group group3",
        "NAT rule 10 has nonexistent destination port group group4",
    ], "Errors added"
Ejemplo n.º 12
0
def test_string():
    """
    .
    """
    rule = NATRule(123, ".")
    assert str(rule) == "NAT rule 123", "String correct"