28{
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]