Skip to content
API Documentation
BastionGuard™
PolicyLoaderTests.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include <cassert>
6#include <filesystem>
7#include <fstream>
8#include <iostream>
9#include <stdexcept>
10#include <string>
11
12namespace {
13
14template <typename Function>
15bool throwsRuntimeError(Function&& function)
16{
17 try {
18 function();
19 } catch (const std::runtime_error&) {
20 return true;
21 }
22 return false;
23}
24
25} // namespace
26
27int main()
28{
29 namespace rg = bastionguard::rootguard;
30
31 const auto directory = std::filesystem::temp_directory_path() /
32 "bastionguard-rootguard-policy-tests";
33 std::filesystem::remove_all(directory);
34 std::filesystem::create_directories(directory);
35
36 const auto path = directory / "valid.conf";
37 {
38 std::ofstream output(path);
39 output << R"(
40[engine]
41version = 2
42mode = enforce
43unknown_action = block
44metadata_action = block
45global_metadata_action = audit
46credential_anomaly_action = block
47allow_missing_paths = true
48require_root_owned_trusted_executables = false
49protect_trusted_executables = true
50monitor_global_privilege_metadata = true
51detect_global_metadata_bursts = true
52global_metadata_sample_limit = 5
53metadata_burst_threshold = 32
54metadata_burst_window_ms = 2500
55metadata_burst_cooldown_ms = 60000
56ignore_run_global_metadata = false
57integrity_poll_seconds = 3
58log_trusted = true
59auto_block_system_services = false
60block_user_home = false
61event_log = /tmp/rootguard-test.jsonl
62
63[trusted-applications]
64path = /usr/bin/firefox
65
66[trusted-executables]
67path = /usr/bin/sudo
68required_path = /usr/bin/su
69
70[denied-executables]
71path = /tmp/evil
72
73[protected-paths]
74required_path = /etc/sudoers
75recursive_path = /etc/pam.d
76
77[ignored-paths]
78path = /etc/cron.d/bastionguard-backup-hourly
79recursive_path = /var/lib/bastionguard/generated
80)";
81 }
82
83 const auto policy = rg::PolicyLoader::load(path);
84 assert(policy.version == 2);
85 assert(policy.mode == rg::Mode::Enforce);
86 assert(policy.unknownAction == rg::Action::Block);
87 assert(policy.metadataAction == rg::Action::Block);
88 assert(policy.globalMetadataAction == rg::Action::Audit);
89 assert(policy.credentialAnomalyAction == rg::Action::Block);
90 assert(policy.detectGlobalMetadataBursts);
91 assert(policy.globalMetadataSampleLimit == 5);
92 assert(policy.metadataBurstThreshold == 32);
93 assert(policy.metadataBurstWindowMs == 2500);
94 assert(policy.metadataBurstCooldownMs == 60000);
95 assert(!policy.ignoreRunGlobalMetadata);
96 assert(policy.integrityPollSeconds == 3);
97 assert(!policy.autoBlockSystemServices);
98 assert(!policy.blockUserHome);
99 assert(policy.trustedApplications.size() == 1);
100 assert(policy.trustedApplications.at(0).id == 1);
101 assert(policy.trustedExecutables.size() == 2);
102 assert(policy.trustedExecutables.at(1).required);
103 assert(policy.deniedExecutables.size() == 1);
104 assert(policy.deniedExecutables.at(0).id == 4);
105 assert(policy.protectedPaths.size() == 2);
106 assert(policy.protectedPaths.at(0).id == 5);
107 assert(policy.protectedPaths.at(0).required);
108 assert(!policy.protectedPaths.at(0).recursive);
109 assert(policy.protectedPaths.at(1).id == 6);
110 assert(policy.protectedPaths.at(1).recursive);
111 assert(policy.ignoredPaths.size() == 2);
112 assert(policy.ignoredPaths.at(0).id == 7);
113 assert(!policy.ignoredPaths.at(0).recursive);
114 assert(policy.ignoredPaths.at(1).id == 8);
115 assert(policy.ignoredPaths.at(1).recursive);
116
117 const std::string unsafeGlobalBlock = R"(
118[engine]
119version = 2
120mode = enforce
121global_metadata_action = block
122monitor_global_privilege_metadata = true
123)";
124 assert(throwsRuntimeError([&] {
125 (void)rg::PolicyLoader::loadFromText(
126 unsafeGlobalBlock, "unsafe-global-block.conf");
127 }));
128
129 const std::string unsafeBurstWindow = R"(
130[engine]
131version = 2
132metadata_burst_threshold = 4
133metadata_burst_window_ms = 100
134metadata_burst_cooldown_ms = 50
135)";
136 assert(throwsRuntimeError([&] {
137 (void)rg::PolicyLoader::loadFromText(
138 unsafeBurstWindow, "unsafe-burst-window.conf");
139 }));
140
141 const std::string trustedApplicationDeniedConflict = R"(
142[engine]
143version = 2
144mode = audit
145[trusted-applications]
146path = /usr/bin/firefox
147[denied-executables]
148path = /usr/bin/firefox
149)";
150 assert(throwsRuntimeError([&] {
151 (void)rg::PolicyLoader::loadFromText(
152 trustedApplicationDeniedConflict, "trusted-app-conflict.conf");
153 }));
154
155 const std::string noTrusted = R"(
156[engine]
157version = 2
158mode = enforce
159unknown_action = block
160metadata_action = audit
161credential_anomaly_action = block
162)";
163 assert(throwsRuntimeError([&] {
164 (void)rg::PolicyLoader::loadFromText(noTrusted, "no-trusted.conf");
165 }));
166
167 const auto symlink = directory / "policy-link.conf";
168 std::filesystem::create_symlink(path, symlink);
169 assert(throwsRuntimeError([&] {
170 (void)rg::PolicySecurity::read(symlink, false);
171 }));
172
173 std::filesystem::permissions(
174 path,
175 std::filesystem::perms::owner_read |
176 std::filesystem::perms::owner_write |
177 std::filesystem::perms::group_write,
178 std::filesystem::perm_options::replace);
179 assert(throwsRuntimeError([&] {
180 (void)rg::PolicySecurity::read(path, true);
181 }));
182
183 std::filesystem::remove_all(directory);
184 std::cout << "PolicyLoaderTests: OK\n";
185 return 0;
186}
int main(int argc, char *argv[])