blob: 287305687869d3d1e65665c5e19a439f65da5c14 [file] [log] [blame]
Václav Kubernátd386aba2021-01-19 10:03:28 +01001/*
2 * Copyright (C) 2021 CESNET, https://photonics.cesnet.cz/
3 *
4 * Written by Václav Kubernát <kubernat@cesnet.cz>
5 *
6*/
7
8#include "trompeloeil_doctest.h"
Václav Kubernát7efd6d52021-11-09 01:31:11 +01009#include <sysrepo-cpp/Connection.hpp>
Václav Kubernátd386aba2021-01-19 10:03:28 +010010#include "firewall/Firewall.h"
11#include "test_log_setup.h"
12
13class MockNft {
14public:
15 MAKE_MOCK1(consumeConfig, void(const std::string&));
16 void operator()(const std::string& config)
17 {
18 consumeConfig(config);
19 }
20};
21
22const std::string NFTABLES_OUTPUT_START = R"(flush ruleset
23add table inet filter
24add chain inet filter acls { type filter hook input priority 0; }
25add rule inet filter acls ct state established,related accept
26add rule inet filter acls iif lo accept comment "Accept any localhost traffic"
27)";
28
Václav Kubernát7efd6d52021-11-09 01:31:11 +010029const auto TIMEOUT = std::chrono::milliseconds{1000};
30
Václav Kubernátd386aba2021-01-19 10:03:28 +010031TEST_CASE("nftables generator")
32{
Václav Kubernát7efd6d52021-11-09 01:31:11 +010033 TEST_SYSREPO_INIT_LOGS;
34 sysrepo::Connection srConn;
35 auto srSess = srConn.sessionStart();
Václav Kubernátd386aba2021-01-19 10:03:28 +010036 // Delete all acls at the start so we know what we're dealing with.
Václav Kubernát7efd6d52021-11-09 01:31:11 +010037 srSess.deleteItem("/ietf-access-control-list:acls");
38 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +010039 MockNft nft;
40
41 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
42 velia::firewall::SysrepoFirewall fw(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);});
43 std::string inputData;
44 std::string expectedOutput;
45
46 SECTION("empty ACL start")
47 {
48 // Add an empty ACL
49 {
50 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
Václav Kubernát7efd6d52021-11-09 01:31:11 +010051 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
52 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +010053 }
54
55 SECTION("add an IPv4 ACE")
56 {
57 expectedOutput = NFTABLES_OUTPUT_START +
58 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010059 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +010060 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
61 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +010062 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
Václav Kubernátd386aba2021-01-19 10:03:28 +010063 }
64
65 SECTION("add an IPv6 ACE")
66 {
67 expectedOutput = NFTABLES_OUTPUT_START +
68 "add rule inet filter acls ip6 saddr 2001:db8:85a3::8a2e:370:7334/128 accept comment \"deny an ipv6 address\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010069 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +010070 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny an ipv6 address']/matches/ipv6/source-ipv6-network",
71 "2001:0db8:85a3:0000:0000:8a2e:0370:7334/128");
Václav Kubernát7efd6d52021-11-09 01:31:11 +010072 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny an ipv6 address']/actions/forwarding", "accept");
Václav Kubernátd386aba2021-01-19 10:03:28 +010073 }
74
75 SECTION("add ACE without 'matches'")
76 {
77 expectedOutput = NFTABLES_OUTPUT_START +
78 "add rule inet filter acls drop comment \"drop eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010079 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='drop eveything']/actions/forwarding", "drop");
Václav Kubernátd386aba2021-01-19 10:03:28 +010080 }
81
82 SECTION("add ACE with 'reject'")
83 {
84 expectedOutput = NFTABLES_OUTPUT_START +
85 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010086 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
Václav Kubernátd386aba2021-01-19 10:03:28 +010087 }
88
89 SECTION("add ACE with 'reject'")
90 {
91 expectedOutput = NFTABLES_OUTPUT_START +
92 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010093 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
Václav Kubernátd386aba2021-01-19 10:03:28 +010094 }
95
96 SECTION("add two ACEs")
97 {
98 expectedOutput = NFTABLES_OUTPUT_START +
99 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
100 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100101 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100102 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
103 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100104 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
105 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100106 }
107
108 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100109 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100110
111 }
112
113 SECTION("non-empty ACL start")
114 {
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100115 // Add a non-empty ACL
Václav Kubernátd386aba2021-01-19 10:03:28 +0100116 {
117 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START +
118 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"));
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100119 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
120 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100121 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
122 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100123 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
124 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100125 }
126
127 SECTION("add another ACE")
128 {
129 expectedOutput = NFTABLES_OUTPUT_START +
130 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
131 "add rule inet filter acls ip saddr 192.168.13.0/24 drop comment \"also deny 192.168.13.0/24\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100132 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100133 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='also deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
134 "192.168.13.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100135 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='also deny 192.168.13.0/24']/actions/forwarding", "drop");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100136
137 }
138
139 SECTION("remove ACE")
140 {
141 expectedOutput = NFTABLES_OUTPUT_START;
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100142 srSess.deleteItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100143 }
144
145 SECTION("remove previous ACE and add another")
146 {
147 expectedOutput = NFTABLES_OUTPUT_START +
148 "add rule inet filter acls ip saddr 192.168.13.0/24 drop comment \"deny 192.168.13.0/24\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100149 srSess.deleteItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']");
150 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100151 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
152 "192.168.13.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100153 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.13.0/24']/actions/forwarding", "drop");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100154 }
155
156 SECTION("remove entire ACL")
157 {
158 expectedOutput = NFTABLES_OUTPUT_START;
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100159 srSess.deleteItem("/ietf-access-control-list:acls/acl[name='acls']");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100160 }
161
162 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100163 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100164 }
165}