// SPDX-License-Identifier: GPL-3.0-or-later package config import ( "os" "path/filepath" "testing" "time" ) func TestDefaultsMatchPython(t *testing.T) { cfg := Default() if cfg.SampleInterval != 4*time.Second || cfg.Cooldown != 60*time.Second || cfg.BaselineGrace != 10*time.Second || cfg.SUIDRefresh != time.Hour || cfg.SUIDScanInterval != time.Minute || cfg.HeartbeatMaxAge != 120 || cfg.MaxSnapshots != 300 || cfg.MaxSnapshotAgeDays != 60 || !cfg.IncidentTracking || cfg.IncidentWindow != 1800 || cfg.IncidentLineageDepth != 8 || !cfg.FirstSeenEnabled { t.Fatalf("unexpected defaults: %+v", cfg) } if !cfg.Enabled("deleted_exe") { t.Fatal("deleted_exe must be enabled by default") } } func TestLoadFlatTOMLAndMultilineDetectorArray(t *testing.T) { path := filepath.Join(t.TempDir(), "sentinel.toml") raw := []byte(` sample_interval = 1.5 # seconds cooldown = 30 baseline_grace = 2.5 suid_refresh = 120 suid_scan_interval = 15 heartbeat_max_age = 45 max_snapshots = 25 max_snapshot_age_days = 7 incident_tracking = false incident_window = 90 incident_lineage_depth = 3 detectors = [ "deleted_exe", "egress", ] input_snooper_allow_comms = ["Xorg"] credential_access_allow_comms = ["firefox"] credential_access_extra_paths = ["/srv/secrets/"] interpreters = ["bash", "python3"] egress_allow_cidrs = ["203.0.113.0/24"] listener_allow_ports = ["22"] listener_allow_comms = ["syncthing"] suppress_package_owned_listeners = true first_seen_enabled = false suid_hot_dirs = ["/tmp"] suid_scan_extra_dirs = ["/dev/shm"] watch_persistence = ["/etc/cron.d"] stealth_network_allow_comms = ["tcpdump"] stealth_network_allow_kinds = ["mptcp"] memory_obfuscation_allow_comms = ["jit-runtime"] memory_obfuscation_allow_paths = ["/tmp/known-profiler/"] exec_rules_file = "/etc/enodia-extra-rules.toml" unknown_future_key = true `) if err := os.WriteFile(path, raw, 0o600); err != nil { t.Fatal(err) } cfg, err := Load(path) if err != nil { t.Fatal(err) } if cfg.SampleInterval != 1500*time.Millisecond || cfg.Cooldown != 30*time.Second || cfg.BaselineGrace != 2500*time.Millisecond || cfg.SUIDRefresh != 2*time.Minute || cfg.SUIDScanInterval != 15*time.Second || cfg.HeartbeatMaxAge != 45 || cfg.MaxSnapshots != 25 || cfg.MaxSnapshotAgeDays != 7 || cfg.IncidentTracking || cfg.IncidentWindow != 90 || cfg.IncidentLineageDepth != 3 { t.Fatalf("unexpected parsed config: %+v", cfg) } if !cfg.Enabled("deleted_exe") || !cfg.Enabled("egress") || cfg.Enabled("reverse_shell") { t.Fatalf("unexpected detector set: %#v", cfg.Detectors) } if !cfg.InputSnooperAllowComms["Xorg"] || cfg.InputSnooperAllowComms["sway"] { t.Fatalf("unexpected input allowlist: %#v", cfg.InputSnooperAllowComms) } if !cfg.CredentialAccessAllowComms["firefox"] || len(cfg.CredentialAccessExtraPaths) != 1 { t.Fatalf("unexpected credential tuning: %#v %#v", cfg.CredentialAccessAllowComms, cfg.CredentialAccessExtraPaths) } if !cfg.Interpreters["bash"] || len(cfg.EgressAllowCIDRs) != 1 { t.Fatalf("unexpected network tuning: %#v %#v", cfg.Interpreters, cfg.EgressAllowCIDRs) } if !cfg.ListenerAllowPorts["22"] || !cfg.ListenerAllowComms["syncthing"] || !cfg.SuppressPackageOwnedListeners || cfg.FirstSeenEnabled || cfg.Enabled("first_seen") || len(cfg.SUIDHotDirs) != 1 || len(cfg.SUIDScanExtraDirs) != 1 || len(cfg.WatchPersistence) != 1 { t.Fatalf("unexpected baseline tuning: %+v", cfg) } if !cfg.StealthNetworkAllowComms["tcpdump"] || !cfg.StealthNetworkAllowKinds["mptcp"] { t.Fatalf("unexpected stealth tuning: %#v %#v", cfg.StealthNetworkAllowComms, cfg.StealthNetworkAllowKinds) } if !cfg.MemoryObfuscationAllowComms["jit-runtime"] || len(cfg.MemoryObfuscationAllowPaths) != 1 || cfg.MemoryObfuscationAllowPaths[0] != "/tmp/known-profiler/" || cfg.ExecRulesFile != "/etc/enodia-extra-rules.toml" { t.Fatalf("unexpected memory tuning: %#v %#v", cfg.MemoryObfuscationAllowComms, cfg.MemoryObfuscationAllowPaths) } } func TestMissingFileKeepsDefaults(t *testing.T) { cfg, err := Load(filepath.Join(t.TempDir(), "missing.toml")) if err != nil { t.Fatal(err) } if !cfg.Enabled("deleted_exe") { t.Fatal("missing config should retain defaults") } }