blob: 2be2e00b3e412d8b34c2ee297e2c2b29ed28ae2d [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
Václav Kubernát68b85c42022-03-29 00:08:23 +020041 SECTION("include files")
42 {
43 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START + "include \"/some/file\"\n"));
44 velia::firewall::SysrepoFirewall fwWithIncludes(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);}, {"/some/file"});
45 }
46
Václav Kubernátd386aba2021-01-19 10:03:28 +010047 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
48 velia::firewall::SysrepoFirewall fw(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);});
49 std::string inputData;
50 std::string expectedOutput;
51
52 SECTION("empty ACL start")
53 {
54 // Add an empty ACL
55 {
56 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
Václav Kubernát7efd6d52021-11-09 01:31:11 +010057 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
58 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +010059 }
60
61 SECTION("add an IPv4 ACE")
62 {
63 expectedOutput = NFTABLES_OUTPUT_START +
64 "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 +010065 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +010066 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
67 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +010068 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 +010069 }
70
71 SECTION("add an IPv6 ACE")
72 {
73 expectedOutput = NFTABLES_OUTPUT_START +
74 "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 +010075 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +010076 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny an ipv6 address']/matches/ipv6/source-ipv6-network",
77 "2001:0db8:85a3:0000:0000:8a2e:0370:7334/128");
Václav Kubernát7efd6d52021-11-09 01:31:11 +010078 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 +010079 }
80
81 SECTION("add ACE without 'matches'")
82 {
83 expectedOutput = NFTABLES_OUTPUT_START +
84 "add rule inet filter acls drop comment \"drop eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010085 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 +010086 }
87
88 SECTION("add ACE with 'reject'")
89 {
90 expectedOutput = NFTABLES_OUTPUT_START +
91 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010092 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 +010093 }
94
95 SECTION("add ACE with 'reject'")
96 {
97 expectedOutput = NFTABLES_OUTPUT_START +
98 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +010099 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 +0100100 }
101
102 SECTION("add two ACEs")
103 {
104 expectedOutput = NFTABLES_OUTPUT_START +
105 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
106 "add rule inet filter acls reject comment \"reject eveything\"\n";
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100107 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100108 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
109 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100110 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
111 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 +0100112 }
113
114 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100115 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100116
117 }
118
119 SECTION("non-empty ACL start")
120 {
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100121 // Add a non-empty ACL
Václav Kubernátd386aba2021-01-19 10:03:28 +0100122 {
123 REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START +
124 "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 +0100125 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/type", "mixed-eth-ipv4-ipv6-acl-type");
126 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100127 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/matches/ipv4/source-ipv4-network",
128 "192.168.0.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100129 srSess.setItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']/actions/forwarding", "drop");
130 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100131 }
132
133 SECTION("add another ACE")
134 {
135 expectedOutput = NFTABLES_OUTPUT_START +
136 "add rule inet filter acls ip saddr 192.168.0.0/24 drop comment \"deny 192.168.0.0/24\"\n"
137 "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 +0100138 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100139 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='also deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
140 "192.168.13.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100141 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 +0100142
143 }
144
145 SECTION("remove ACE")
146 {
147 expectedOutput = NFTABLES_OUTPUT_START;
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100148 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 +0100149 }
150
151 SECTION("remove previous ACE and add another")
152 {
153 expectedOutput = NFTABLES_OUTPUT_START +
154 "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 +0100155 srSess.deleteItem("/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.0.0/24']");
156 srSess.setItem(
Václav Kubernátd386aba2021-01-19 10:03:28 +0100157 "/ietf-access-control-list:acls/acl[name='acls']/aces/ace[name='deny 192.168.13.0/24']/matches/ipv4/source-ipv4-network",
158 "192.168.13.0/24");
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100159 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 +0100160 }
161
162 SECTION("remove entire ACL")
163 {
164 expectedOutput = NFTABLES_OUTPUT_START;
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100165 srSess.deleteItem("/ietf-access-control-list:acls/acl[name='acls']");
Václav Kubernátd386aba2021-01-19 10:03:28 +0100166 }
167
168 REQUIRE_CALL(nft, consumeConfig(expectedOutput));
Václav Kubernát7efd6d52021-11-09 01:31:11 +0100169 srSess.applyChanges(TIMEOUT);
Václav Kubernátd386aba2021-01-19 10:03:28 +0100170 }
171}