firewall/nftables: Add support for include files
Change-Id: Ibeebf4e764cab175bac6ca21485526569c261123
diff --git a/src/firewall/Firewall.cpp b/src/firewall/Firewall.cpp
index ca11f47..a9352bd 100644
--- a/src/firewall/Firewall.cpp
+++ b/src/firewall/Firewall.cpp
@@ -23,7 +23,7 @@
const auto action = "/ietf-access-control-list:acls/acl/aces/ace/actions/forwarding";
}
-std::string generateNftConfig(velia::Log logger, const libyang::DataNode& tree)
+std::string generateNftConfig(velia::Log logger, const libyang::DataNode& tree, const std::vector<std::filesystem::path>& nftIncludes)
{
using namespace std::string_view_literals;
std::ostringstream ss;
@@ -99,11 +99,15 @@
}
}
+ for (const auto& path : nftIncludes) {
+ ss << "include \"" << path.c_str() << "\"\n";
+ }
+
return ss.str();
}
}
-velia::firewall::SysrepoFirewall::SysrepoFirewall(sysrepo::Session srSess, NftConfigConsumer consumer)
+velia::firewall::SysrepoFirewall::SysrepoFirewall(sysrepo::Session srSess, NftConfigConsumer consumer, const std::vector<std::filesystem::path>& nftIncludeFiles)
: m_sub()
, m_log(spdlog::get("firewall"))
{
@@ -111,11 +115,11 @@
utils::ensureModuleImplemented(srSess, "ietf-access-control-list", "2019-03-04");
utils::ensureModuleImplemented(srSess, "czechlight-firewall", "2021-01-25");
- sysrepo::ModuleChangeCb cb = [logger = m_log, consumer = std::move(consumer)] (sysrepo::Session session, auto, auto, auto, auto, auto) {
+ sysrepo::ModuleChangeCb cb = [nftIncludeFiles, logger = m_log, consumer = std::move(consumer)] (sysrepo::Session session, auto, auto, auto, auto, auto) {
logger->debug("Applying new data from sysrepo");
auto data = session.getData("/" + ietf_acl_module + ":*");
- auto config = generateNftConfig(logger, *data);
+ auto config = generateNftConfig(logger, *data, nftIncludeFiles);
logger->trace("running the consumer...");
consumer(config);
logger->trace("consumer done.");
diff --git a/src/firewall/Firewall.h b/src/firewall/Firewall.h
index d15589e..d52e656 100644
--- a/src/firewall/Firewall.h
+++ b/src/firewall/Firewall.h
@@ -12,7 +12,7 @@
class SysrepoFirewall {
public:
using NftConfigConsumer = std::function<void(const std::string& config)>;
- SysrepoFirewall(sysrepo::Session srSess, NftConfigConsumer consumer);
+ SysrepoFirewall(sysrepo::Session srSess, NftConfigConsumer consumer, const std::vector<std::filesystem::path>& nftIncludeFiles = {});
private:
std::optional<sysrepo::Subscription> m_sub;
diff --git a/src/main-firewall.cpp b/src/main-firewall.cpp
index 5772f2f..f96f542 100644
--- a/src/main-firewall.cpp
+++ b/src/main-firewall.cpp
@@ -22,6 +22,7 @@
veliad-firewall
[--sysrepo-log-level=<Level>]
[--firewall-log-level=<Level>]
+ [--nftables-include-file=<Path>]...
veliad-firewall (-h | --help)
veliad-firewall --version
@@ -32,6 +33,7 @@
--sysrepo-log-level=<N> Log level for the sysrepo library [default: 2]
(0 -> critical, 1 -> error, 2 -> warning, 3 -> info,
4 -> debug, 5 -> trace)
+ --nftables-include-file=<Path> Files to include in the nftables config file.
)";
int main(int argc, char* argv[])
@@ -53,6 +55,11 @@
spdlog::get("firewall")->set_level(parseLogLevel("Firewall logging", args["--firewall-log-level"]));
spdlog::get("sysrepo")->set_level(parseLogLevel("Sysrepo library", args["--sysrepo-log-level"]));
+ std::vector<std::filesystem::path> nftIncludeFiles;
+ for (const auto& path : args["--nftables-include-file"].asStringList()) {
+ nftIncludeFiles.emplace_back(path);
+ }
+
auto srConn = sysrepo::Connection{};
auto srSess = srConn.sessionStart();
velia::firewall::SysrepoFirewall firewall(srSess, [] (const auto& config) {
@@ -60,7 +67,7 @@
velia::utils::execAndWait(spdlog::get("firewall"), NFT_EXECUTABLE, {"-f", "-"}, config);
spdlog::get("firewall")->debug("nft config applied.");
- });
+ }, nftIncludeFiles);
waitUntilSignaled();
diff --git a/tests/sysrepo-firewall.cpp b/tests/sysrepo-firewall.cpp
index 2873056..2be2e00 100644
--- a/tests/sysrepo-firewall.cpp
+++ b/tests/sysrepo-firewall.cpp
@@ -38,6 +38,12 @@
srSess.applyChanges(TIMEOUT);
MockNft nft;
+ SECTION("include files")
+ {
+ REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START + "include \"/some/file\"\n"));
+ velia::firewall::SysrepoFirewall fwWithIncludes(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);}, {"/some/file"});
+ }
+
REQUIRE_CALL(nft, consumeConfig(NFTABLES_OUTPUT_START));
velia::firewall::SysrepoFirewall fw(srSess, [&nft] (const std::string& config) {nft.consumeConfig(config);});
std::string inputData;