blob: 0daf255c0f76c82b2b3eaf7bfc7390b2f479cbba [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"
9#include "firewall/Firewall.h"
10#include "test_log_setup.h"
11
12class MockNft {
13public:
14 MAKE_MOCK1(consumeConfig, void(const std::string&));
15 void operator()(const std::string& config)
16 {
17 consumeConfig(config);
18 }
19};
20
21const std::string NFTABLES_OUTPUT_START = R"(flush ruleset
22add table inet filter
23add chain inet filter acls { type filter hook input priority 0; }
24add rule inet filter acls ct state established,related accept
25add rule inet filter acls iif lo accept comment "Accept any localhost traffic"
26)";
27
28TEST_CASE("nftables generator")
29{
30 TEST_INIT_LOGS;
31 auto srConn = std::make_shared<sysrepo::Connection>();
32 auto srSess = std::make_shared<sysrepo::Session>(srConn);
33 // Delete all acls at the start so we know what we're dealing with.
34 srSess->delete_item("/ietf-access-control-list:acls");
35 srSess->apply_changes(1000, 1);
36 MockNft nft;
37
38 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
39 velia::firewall::SysrepoFirewall fw(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);});
40 std::string inputData;
41 std::string expectedOutput;
42
43 SECTION("empty ACL start")
44 {
45 // Add an empty ACL
46 {
47 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
48 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
49 srSess->apply_changes(1000, 1);
50 }
51
52 SECTION("add an IPv4 ACE")
53 {
54 expectedOutput = NFTABLES_OUTPUT_START +
55 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n";
56 srSess->set_item_str(
57 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
58 "192.168.0.0/24");
59 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
60 }
61
62 SECTION("add an IPv6 ACE")
63 {
64 expectedOutput = NFTABLES_OUTPUT_START +
65 "add rule inet filter acls ip6 saddr 2001:db8:85a3::8a2e:370:7334/128 accept comment \"deny an ipv6 address\"\n";
66 srSess->set_item_str(
67 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny an ipv6 address']/matches/ipv6/source-ipv6-network",
68 "2001:0db8:85a3:0000:0000:8a2e:0370:7334/128");
69 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny an ipv6 address']/actions/forwarding", "accept");
70 }
71
72 SECTION("add ACE without 'matches'")
73 {
74 expectedOutput = NFTABLES_OUTPUT_START +
75 "add rule inet filter acls drop comment \"drop eveything\"\n";
76 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='drop eveything']/actions/forwarding", "drop");
77 }
78
79 SECTION("add ACE with 'reject'")
80 {
81 expectedOutput = NFTABLES_OUTPUT_START +
82 "add rule inet filter acls reject comment \"reject eveything\"\n";
83 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
84 }
85
86 SECTION("add ACE with 'reject'")
87 {
88 expectedOutput = NFTABLES_OUTPUT_START +
89 "add rule inet filter acls reject comment \"reject eveything\"\n";
90 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
91 }
92
93 SECTION("add two ACEs")
94 {
95 expectedOutput = NFTABLES_OUTPUT_START +
96 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
97 "add rule inet filter acls reject comment \"reject eveything\"\n";
98 srSess->set_item_str(
99 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
100 "192.168.0.0/24");
101 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
102 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='reject eveything']/actions/forwarding", "reject");
103 }
104
105 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
106 srSess->apply_changes(1000, 1);
107
108 }
109
110 SECTION("non-empty ACL start")
111 {
112 // Add an non-empty ACL
113 {
114 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START +
115 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"));
116 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
117 srSess->set_item_str(
118 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
119 "192.168.0.0/24");
120 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
121 srSess->apply_changes(1000, 1);
122 }
123
124 SECTION("add another ACE")
125 {
126 expectedOutput = NFTABLES_OUTPUT_START +
127 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
128 "add rule inet filter acls ip saddr 192.168.13.0/24 drop comment \"also deny 192.168.13.0/24\"\n";
129 srSess->set_item_str(
130 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='also deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
131 "192.168.13.0/24");
132 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='also deny 192.168.13.0/24']/actions/forwarding", "drop");
133
134 }
135
136 SECTION("remove ACE")
137 {
138 expectedOutput = NFTABLES_OUTPUT_START;
139 srSess->delete_item("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']");
140 }
141
142 SECTION("remove previous ACE and add another")
143 {
144 expectedOutput = NFTABLES_OUTPUT_START +
145 "add rule inet filter acls ip saddr 192.168.13.0/24 drop comment \"deny 192.168.13.0/24\"\n";
146 srSess->delete_item("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']");
147 srSess->set_item_str(
148 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
149 "192.168.13.0/24");
150 srSess->set_item_str("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.13.0/24']/actions/forwarding", "drop");
151 }
152
153 SECTION("remove entire ACL")
154 {
155 expectedOutput = NFTABLES_OUTPUT_START;
156 srSess->delete_item("/ietf-access-control-list:acls/acl[name='acls']");
157 }
158
159 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
160 srSess->apply_changes(1000, 1);
161 }
162}