• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Achiefs / fim / 14275166216

04 Apr 2025 10:13PM UTC coverage: 84.711% (-0.4%) from 85.125%
14275166216

push

github

web-flow
Merge pull request #194 from Achiefs/177-db-hash

Added Hash diff scanner

353 of 433 new or added lines in 12 files covered. (81.52%)

4 existing lines in 1 file now uncovered.

1435 of 1694 relevant lines covered (84.71%)

1.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.03
/src/appconfig.rs
1
// Copyright (C) 2021, Achiefs.
2

3
// Global constants definitions
4
pub const VERSION: &str = "0.6.0";
5
pub const NETWORK_MODE: &str = "NETWORK";
6
pub const FILE_MODE: &str = "FILE";
7
pub const BOTH_MODE: &str = "BOTH";
8
pub const MACHINE_ID_PATH: &str = "/etc/machine-id";
9
const CONFIG_MACOS_PATH: &str = "/Applications/FileMonitor.app/config.yml";
10
const CONFIG_LINUX_PATH: &str = "/etc/fim/config.yml";
11
const CONFIG_WINDOWS_PATH: &str = "C:\\Program Files\\File Integrity Monitor\\config.yml";
12

13
// Required dependencies
14
use yaml_rust::yaml::{Yaml, YamlLoader, Array};
15
use std::fs::{File, OpenOptions};
16
use std::io::{Read, Write};
17
use std::path::Path;
18
use simplelog::LevelFilter;
19
use std::sync::{Arc, Mutex};
20
use log::error;
21

22
use crate::utils;
23
use crate::integration::Integration;
24
use crate::hash::ShaType;
25

26
// ----------------------------------------------------------------------------
27

28
#[derive(Clone)]
29
pub struct AppConfig {
30
    pub version: String,
31
    pub path: String,
32
    pub events_watcher: String,
33
    pub events_destination: String,
34
    pub events_max_file_checksum: usize,
35
    pub events_max_file_size: usize,
36
    pub checksum_algorithm: ShaType,
37
    pub endpoint_type: String,
38
    pub endpoint_address: String,
39
    pub endpoint_user: String,
40
    pub endpoint_pass: String,
41
    pub endpoint_token: String,
42
    pub events_file: String,
43
    pub monitor: Array,
44
    pub audit: Array,
45
    pub node: String,
46
    pub log_file: String,
47
    pub log_level: String,
48
    pub log_max_file_size: usize,
49
    pub system: String,
50
    pub insecure: bool,
51
    pub events_lock: Arc<Mutex<bool>>,
52
    pub log_lock: Arc<Mutex<bool>>,
53
    pub hashscanner_file: String,
54
    pub hashscanner_enabled: bool,
55
    pub hashscanner_interval: usize,
56
    pub hashscanner_algorithm: ShaType,
57
    pub engine: String
58
}
59

60
impl AppConfig {
61

62
    pub fn clone(&self) -> Self {
1✔
63
        AppConfig {
64
            version: self.version.clone(),
1✔
65
            path: self.path.clone(),
1✔
66
            events_watcher: self.events_watcher.clone(),
1✔
67
            events_destination: self.events_destination.clone(),
1✔
68
            events_max_file_checksum: self.events_max_file_checksum,
1✔
69
            events_max_file_size: self.events_max_file_size,
1✔
70
            checksum_algorithm: self.checksum_algorithm.clone(),
1✔
71
            endpoint_type: self.endpoint_type.clone(),
1✔
72
            endpoint_address: self.endpoint_address.clone(),
1✔
73
            endpoint_user: self.endpoint_user.clone(),
1✔
74
            endpoint_pass: self.endpoint_pass.clone(),
1✔
75
            endpoint_token: self.endpoint_token.clone(),
1✔
76
            events_file: self.events_file.clone(),
1✔
77
            monitor: self.monitor.clone(),
1✔
78
            audit: self.audit.clone(),
1✔
79
            node: self.node.clone(),
1✔
80
            log_file: self.log_file.clone(),
1✔
81
            log_level: self.log_level.clone(),
1✔
82
            log_max_file_size: self.log_max_file_size,
1✔
83
            system: self.system.clone(),
1✔
84
            insecure: self.insecure,
1✔
85
            events_lock: self.events_lock.clone(),
2✔
86
            log_lock: self.log_lock.clone(),
2✔
87
            hashscanner_file: self.hashscanner_file.clone(),
1✔
88
            hashscanner_enabled: self.hashscanner_enabled,
1✔
89
            hashscanner_interval: self.hashscanner_interval,
1✔
90
            hashscanner_algorithm: self.hashscanner_algorithm.clone(),
1✔
91
            engine: self.engine.clone()
1✔
92
        }
93
    }
94

95
    pub fn new(system: &str, config_path: Option<&str>) -> Self {
2✔
96
        println!("[INFO] System detected '{}'", system);
1✔
97
        let cfg = match config_path {
1✔
98
            Some(path) => String::from(path),
1✔
99
            None => get_config_path(system)
1✔
100
        };
101
        println!("[INFO] Loaded config from: '{}'", cfg);
2✔
102
        let yaml = read_config(cfg.clone());
1✔
103

104
        // Manage null value on events->destination value
105
        let events_destination = match yaml[0]["events"]["destination"].as_str() {
2✔
106
            Some(value) => String::from(value),
2✔
107
            None => {
108
                println!("[WARN] events->destination not found in config.yml, using 'file'.");
2✔
109
                String::from("file")
1✔
110
            }
111
        };
112

113
        // Manage value on events->watcher value
114
        let events_watcher = match yaml[0]["events"]["watcher"].as_str() {
2✔
115
            Some("poll"|"P"|"POLL"|"Poll") => String::from("Poll"),
2✔
116
            _ => String::from("Recommended")
2✔
117
        };
118

119
        // Manage null value on events->file value
120
        let events_file = match yaml[0]["events"]["file"].as_str() {
2✔
121
            Some(value) => String::from(value),
2✔
122
            None => {
123
                if events_destination != *"network" {
4✔
124
                    println!("[ERROR] events->file not found in config.yml.");
2✔
125
                    panic!("events->file not found in config.yml.");
1✔
126
                }else{
127
                    String::from("Not_defined")
2✔
128
                }
129
            }
130
        };
131

132
        // Manage null value on events->max_file_checksum value
133
        let events_max_file_checksum = match yaml[0]["events"]["max_file_checksum"].as_i64() {
2✔
134
            Some(value) => usize::try_from(value).unwrap(),
2✔
135
            None => 64
1✔
136
        };
137

138
        // Manage null value on events->max_file_size value
139
        let events_max_file_size = match yaml[0]["events"]["max_file_size"].as_i64() {
2✔
140
            Some(value) => usize::try_from(value).unwrap(),
2✔
141
            None => 128
1✔
142
        };
143

144
        // Temporal value
145
        let checksum_algorithm = match yaml[0]["events"]["checksum_algorithm"].as_str() {
2✔
NEW
146
            Some(value) => {
×
147
                match value {
NEW
148
                    "sha224"|"224"|"SHA224"|"Sha224" => ShaType::Sha224,
×
NEW
149
                    "sha256"|"256"|"SHA256"|"Sha256" => ShaType::Sha256,
×
NEW
150
                    "sha384"|"384"|"SHA384"|"Sha384" => ShaType::Sha384,
×
NEW
151
                    "sha512"|"512"|"SHA512"|"Sha512" => ShaType::Sha512,
×
NEW
152
                    "keccak224"|"K224"|"KECCAK224"|"Keccak224" => ShaType::Keccak224,
×
NEW
153
                    "keccak256"|"K256"|"KECCAK256"|"Keccak256" => ShaType::Keccak256,
×
NEW
154
                    "keccak384"|"K384"|"KECCAK384"|"Keccak384" => ShaType::Keccak384,
×
NEW
155
                    "keccak512"|"K512"|"KECCAK512"|"Keccak512" => ShaType::Keccak512,
×
NEW
156
                    _ => ShaType::Sha512
×
157
                }
158
            },
159
            None => ShaType::Sha256
1✔
160
        };
161

162
        let hashscanner_algorithm = match yaml[0]["hashscanner"]["algorithm"].as_str() {
2✔
NEW
163
            Some(value) => {
×
164
                match value {
NEW
165
                    "sha224"|"224"|"SHA224"|"Sha224" => ShaType::Sha224,
×
NEW
166
                    "sha256"|"256"|"SHA256"|"Sha256" => ShaType::Sha256,
×
NEW
167
                    "sha384"|"384"|"SHA384"|"Sha384" => ShaType::Sha384,
×
NEW
168
                    "sha512"|"512"|"SHA512"|"Sha512" => ShaType::Sha512,
×
NEW
169
                    "keccak224"|"K224"|"KECCAK224"|"Keccak224" => ShaType::Keccak224,
×
NEW
170
                    "keccak256"|"K256"|"KECCAK256"|"Keccak256" => ShaType::Keccak256,
×
NEW
171
                    "keccak384"|"K384"|"KECCAK384"|"Keccak384" => ShaType::Keccak384,
×
NEW
172
                    "keccak512"|"K512"|"KECCAK512"|"Keccak512" => ShaType::Keccak512,
×
NEW
173
                    _ => ShaType::Sha256
×
174
                }
175
            },
176
            None => ShaType::Sha256
1✔
177
        };
178

179
        // Manage null value on events->endpoint->insecure value
180
        let insecure = match yaml[0]["events"]["endpoint"]["insecure"].as_bool() {
2✔
181
            Some(value) => value,
1✔
182
            None => {
183
                if events_destination != *"file" {
4✔
184
                    println!("[WARN] events->endpoint->insecure not found in config.yml, using 'false'.");
4✔
185
                    false
2✔
186
                }else{ false }
1✔
187
            }
188
        };
189

190
        // Manage null value on events->endpoint->address value
191
        let endpoint_address = match yaml[0]["events"]["endpoint"]["address"].as_str() {
2✔
192
            Some(value) => String::from(value),
4✔
193
            None => {
194
                if events_destination != *"file" {
2✔
195
                    println!("[ERROR] events->endpoint->address not found in config.yml.");
2✔
196
                    panic!("events->endpoint->address not found in config.yml.");
1✔
197
                }else{
198
                    String::from("Not_defined")
1✔
199
                }
200
            }
201
        };
202

203
        // Manage null value on events->endpoint->credentials->token value
204
        let endpoint_token = match yaml[0]["events"]["endpoint"]["credentials"]["token"].as_str() {
2✔
205
            Some(value) => String::from(value),
2✔
206
            None => String::from("Not_defined")
2✔
207
        };
208

209
        // Manage null value on events->endpoint->credentials->user value
210
        let endpoint_user = match yaml[0]["events"]["endpoint"]["credentials"]["user"].as_str() {
2✔
211
            Some(value) => String::from(value),
2✔
212
            None => {
213
                if events_destination != *"file" && endpoint_token.is_empty() {
3✔
214
                    println!("[ERROR] events->endpoint->credentials->user not found in config.yml.");
×
215
                    panic!("events->endpoint->credentials->user not found in config.yml.");
×
216
                }else{
217
                    String::from("Not_defined")
1✔
218
                }
219
            }
220
        };
221

222
        // Manage null value on events->endpoint->credentials->password value
223
        let endpoint_pass = match yaml[0]["events"]["endpoint"]["credentials"]["password"].as_str() {
2✔
224
            Some(value) => String::from(value),
2✔
225
            None => {
226
                if events_destination != *"file" && endpoint_token.is_empty()  {
3✔
227
                    println!("[ERROR] events->endpoint->credentials->password not found in config.yml.");
×
228
                    panic!("events->endpoint->credentials->password not found in config.yml.");
×
229
                }else{
230
                    String::from("Not_defined")
1✔
231
                }
232
            }
233
        };
234

235
        let endpoint_type = if endpoint_token != "Not_defined" {
2✔
236
            String::from("Splunk")
2✔
237
        }else if endpoint_user != "Not_defined" && endpoint_pass != "Not_defined" {
3✔
238
            String::from("Elastic")
2✔
239
        }else{
240
            String::from("Not_defined")
2✔
241
        };
242

243
        if endpoint_token == "Not_defined" && (endpoint_user == "Not_defined" ||
3✔
244
            endpoint_pass == "Not_defined") && events_destination != *"file" {
1✔
245
            println!("[ERROR] events->endpoint->credentials->[token or user and password] not found in config.yml.");
2✔
246
            panic!("No endpoint credentials provided in config.yml.");
1✔
247
        }
248

249

250
        // Manage null value on monitor value
251
        let monitor = match yaml[0]["monitor"].as_vec() {
2✔
252
            Some(value) => value.to_vec(),
2✔
253
            None => Vec::new()
2✔
254
        };
255

256
        // Manage null value on audit value
257
        let mut engine = String::from("monitor");
1✔
258
        let audit = match yaml[0]["audit"].as_vec() {
2✔
259
            Some(value) => {
1✔
260
                if utils::get_os() != "linux" {
2✔
261
                    panic!("Audit only supported in Linux systems.");
×
262
                }
263
                engine = String::from("audit");
2✔
264
                value.to_vec()
1✔
265
            },
266
            None => {
267
                if monitor.is_empty() {
3✔
268
                    panic!("Neither monitor or audit section found in config.yml.");
2✔
269
                };
270
                Vec::new()
3✔
271
            }
272
        };
273

274
        // Manage null value on node value
275
        let node = match yaml[0]["node"].as_str() {
2✔
276
            Some(value) => String::from(value),
2✔
277
            None => {
278
                match system {
279
                    "linux" => match utils::get_machine_id().is_empty() {
5✔
280
                        true => utils::get_hostname(),
×
281
                        false => utils::get_machine_id()
2✔
282
                    },
283
                    "macos" => match utils::get_machine_id().is_empty(){
×
284
                        true => utils::get_hostname(),
×
285
                        false => utils::get_machine_id()
×
286
                    }
287
                    _ => {
288
                        println!("[WARN] node not found in config.yml, using hostname.");
×
289
                        utils::get_hostname()
×
290
                    }
291
                }
292
            }
293
        };
294

295
        // Manage null value on log->file value
296
        let log_file = match yaml[0]["log"]["file"].as_str() {
3✔
297
            Some(value) => String::from(value),
2✔
298
            None => {
299
                println!("[ERROR] log->file not found in config.yml.");
2✔
300
                panic!("log->file not found in config.yml.");
1✔
301
            }
302
        };
303

304
        // Manage null value on log->level value
305
        let log_level = match yaml[0]["log"]["level"].as_str() {
2✔
306
            Some(value) => String::from(value),
3✔
307
            None => {
308
                println!("[WARN] log->level not found in config.yml, using 'info'.");
4✔
309
                String::from("info")
2✔
310
            }
311
        };
312

313
        // Manage null value on log->max_file_size value
314
        let log_max_file_size = match yaml[0]["log"]["max_file_size"].as_i64() {
4✔
315
            Some(value) => usize::try_from(value).unwrap(),
×
316
            None => 64
2✔
317
        };
318

319
        // Manage null value on hashscanner->file value
320
        let hashscanner_file = match yaml[0]["hashscanner"]["file"].as_str() {
4✔
321
            Some(value) => String::from(value),
2✔
322
            None => {
323
                println!("[ERROR] hashscanner->file not found in config.yml.");
2✔
324
                panic!("hashscanner->file not found in config.yml.");
1✔
325
            }
326
        };
327

328
        let hashscanner_interval = match yaml[0]["hashscanner"]["interval"].as_i64() {
4✔
NEW
329
            Some(value) => {
×
NEW
330
                let interval = usize::try_from(value).unwrap();
×
NEW
331
                if interval >= 5 { interval * 60 }else{ 300 } // Minimum of five minutes 
×
332
            },
333
            None => 3600 // Default one hour
2✔
334
        };
335

336
        let hashscanner_enabled = yaml[0]["hashscanner"]["enabled"].as_bool().unwrap_or(true);
4✔
337

338
        AppConfig {
339
            version: String::from(VERSION),
4✔
340
            path: cfg,
341
            events_watcher,
342
            events_destination,
343
            events_max_file_checksum,
344
            events_max_file_size,
345
            checksum_algorithm,
346
            endpoint_type,
347
            endpoint_address,
348
            endpoint_user,
349
            endpoint_pass,
350
            endpoint_token,
351
            events_file,
352
            monitor,
353
            audit,
354
            node,
355
            log_file,
356
            log_level,
357
            log_max_file_size,
358
            system: String::from(system),
4✔
359
            insecure,
360
            events_lock: Arc::new(Mutex::new(false)),
8✔
361
            log_lock: Arc::new(Mutex::new(false)),
8✔
362
            hashscanner_file,
363
            hashscanner_enabled,
364
            hashscanner_interval,
365
            hashscanner_algorithm,
366
            engine
367
        }
368
    }
369

370
    // ------------------------------------------------------------------------
371

372
    // To process log level set on config file
373
    pub fn get_level_filter(&self) -> LevelFilter {
1✔
374
        let mut log = OpenOptions::new()
5✔
375
            .create(true)
376
            .append(true)
377
            .open(self.log_file.clone())
4✔
378
            .expect("(get_level_filter) Unable to open events log file.");
379

380
        match self.log_level.as_str() {
8✔
381
            "debug" | "Debug" | "DEBUG" | "D" | "d" => LevelFilter::Debug,
4✔
382
            "info" | "Info" | "INFO" | "I" | "i" => LevelFilter::Info,
3✔
383
            "error" | "Error" | "ERROR" | "E" | "e" => LevelFilter::Error,
1✔
384
            "warning" | "Warning" | "WARNING" | "W" | "w" | "warn" | "Warn" | "WARN" => LevelFilter::Warn,
1✔
385
            _ => {
386
                let msg = String::from("[ERROR] invalid log level from 'config.yml', using Info level.");
1✔
387
                println!("{}", msg);
2✔
388
                writeln!(log, "{}", msg).expect("[ERROR] cannot write in log file.");
1✔
389
                LevelFilter::Info
1✔
390
            }
391
        }
392
    }
393

394
    // ------------------------------------------------------------------------
395

396
    pub fn get_events_destination(&self) -> String {
1✔
397
        match self.events_destination.clone().as_str() {
2✔
398
            "both" => String::from(BOTH_MODE),
3✔
399
            "network" => String::from(NETWORK_MODE),
4✔
400
            // Default option is to log into file
401
            _ => String::from(FILE_MODE)
2✔
402
        }
403
    }
404

405
    // ------------------------------------------------------------------------
406

407
    pub fn get_index(&self, raw_path: &str, cwd: &str, array: Array) -> usize {
2✔
408
        // Iterate over monitoring paths to match ignore string and ignore event or not
409
        match array.iter().position(|it| {
6✔
410
            if !cwd.is_empty() && (raw_path.starts_with("./") || raw_path == "." || !raw_path.contains('/')) {
2✔
411
                utils::match_path(cwd, it["path"].as_str().unwrap())
1✔
412
            }else{
413
                utils::match_path(raw_path, it["path"].as_str().unwrap())
2✔
414
            }
415
        }){
416
            Some(pos) => pos,
2✔
417
            None => usize::MAX
2✔
418
        }
419
    }
420

421
    // ------------------------------------------------------------------------
422

423
    pub fn get_labels(&self, index: usize, array: Array) -> Vec<String> {
1✔
424
        array[index]["labels"].clone().into_vec().unwrap_or_default()
4✔
425
        .to_vec().iter().map(|element| String::from(element.as_str().unwrap()) ).collect()
426
    }
427

428
    // ------------------------------------------------------------------------
429

430
    pub fn match_ignore(&self, index: usize, filename: &str, array: Array) -> bool {
1✔
431
        match array[index]["ignore"].as_vec() {
2✔
432
            Some(igv) => igv.to_vec().iter().any(|ignore| filename.contains(ignore.as_str().unwrap()) ),
4✔
433
            None => false
1✔
434
        }
435
    }
436

437
    // ------------------------------------------------------------------------
438

439
    pub fn match_exclude(&self, index: usize, path: &str, array: Array) -> bool {
1✔
440
        match array[index]["exclude"].as_vec() {
2✔
441
            Some(igv) => igv.to_vec().iter().any(|exclude| path.contains(exclude.as_str().unwrap()) ),
4✔
442
            None => false
×
443
        }
444
    }
445

446
    // ------------------------------------------------------------------------
447

448
    pub fn match_allowed(&self, index: usize, filename: &str, array: Array) -> bool {
1✔
449
        match array[index]["allowed"].as_vec() {
2✔
450
            Some(allowed) => allowed.to_vec().iter().any(|allw| filename.contains(allw.as_str().unwrap())),
4✔
451
            None => true
×
452
        }
453
    }
454

455
    // ------------------------------------------------------------------------
456

457
    // Returns if a given path and filename is in the configuration paths
458
    pub fn path_in(&self, raw_path: &str, cwd: &str, vector: Vec<Yaml>) -> bool {
1✔
459
        // Iterate over monitoring paths to match ignore string and ignore event or not
460
        vector.iter().any(|it| {
3✔
461
            if raw_path.starts_with("./") || raw_path == "." || !raw_path.contains('/') {
2✔
462
                utils::match_path(cwd, it["path"].as_str().unwrap())
1✔
463
            }else{
464
                utils::match_path(raw_path, it["path"].as_str().unwrap())
1✔
465
            }
466
        })
467
    }
468

469
    // ------------------------------------------------------------------------
470

471
    pub fn get_integrations(&self, index: usize, array: Array) -> Vec<Integration> {
1✔
472
        let default = array[index]["integrations"].clone().into_vec();
2✔
473
        let data = default.unwrap_or_default();
1✔
474
        let mut integrations: Vec<Integration> = Vec::new();
1✔
475
        data.iter().for_each(|info|
3✔
476
            integrations.push(Integration::new(
3✔
477
                String::from(info["name"].as_str().unwrap()), 
1✔
478
                info["condition"]
3✔
479
                    .clone().into_vec().unwrap().iter().map(|element| 
1✔
480
                        String::from(element.as_str().unwrap()) ).collect(), 
2✔
481
                String::from(info["binary"].as_str().unwrap()), 
2✔
482
                String::from(info["script"].as_str().unwrap()), 
2✔
483
                String::from(info["parameters"].as_str().unwrap()) ))
2✔
484
        );
485
        integrations
1✔
486
    }
487

488
    // ------------------------------------------------------------------------
489

490
    pub fn get_lock_value(&self, lock: &Arc<Mutex<bool>>) -> bool {
1✔
491
        match Arc::into_inner(lock.into()) {
1✔
492
            None => {
493
                error!("Cannot retrieve events lock Arc value.");
×
494
                false
×
495
            },
496
            Some(mutex) => match mutex.lock() {
1✔
497
                Ok(guard) => *guard,
1✔
498
                Err(e) => {
×
499
                    error!("Cannot retrieve events lock Mutex value, err: {}.", e);
×
500
                    false
×
501
                }
502
            }
503
        }
504
    }
505

506
    // ------------------------------------------------------------------------
507

508
    pub fn get_events_file(&self) -> String {
1✔
509
        match self.get_lock_value(&self.events_lock) {
1✔
510
            false => self.events_file.clone(),
1✔
511
            true => format!("{}.tmp", self.events_file.clone())
×
512
        }
513
    }
514

515
    // ------------------------------------------------------------------------
516

517
    pub fn get_mutex(&self, lock: Arc<Mutex<bool>>) -> Mutex<bool> {
×
518
        match Arc::into_inner(lock.clone()) {
×
519
            None => {
520
                error!("Could not retrieve Mutex '{:?}'.", lock.clone());
×
521
                Mutex::new(false)
×
522
            },
523
            Some(mutex) => mutex
×
524
        }
525
    }
526

527
}
528

529
// ----------------------------------------------------------------------------
530

531
// To read the Yaml configuration file
532
pub fn read_config(path: String) -> Vec<Yaml> {
1✔
533
    let mut file: File = File::open(path.clone())
2✔
534
        .unwrap_or_else(|_| panic!("(read_config): Unable to open file '{}'", path));
2✔
535
    let mut contents: String = String::new();
1✔
536

537
    file.read_to_string(&mut contents)
2✔
538
        .expect("Unable to read file");
539
    YamlLoader::load_from_str(&contents).unwrap()
1✔
540
}
541

542
// ----------------------------------------------------------------------------
543

544
pub fn get_config_path(system: &str) -> String {
1✔
545
    // Select directory where to load config.yml it depends on system
546
    let current_dir: String = utils::get_current_dir();
1✔
547
    if system == "windows" {
3✔
548
        let default_path: String = format!("{}\\config\\{}\\config.yml", current_dir, system);
×
549
        let relative_path: String = format!("{}\\..\\..\\config\\{}\\config.yml", current_dir, system);
×
550
        if Path::new(default_path.as_str()).exists() {
×
551
            default_path
×
552
        }else if Path::new(&format!("{}\\config.yml", current_dir)).exists() {
×
553
            format!("{}\\config.yml", current_dir)
×
554
        }else if Path::new(relative_path.as_str()).exists() {
×
555
            relative_path
×
556
        }else{
557
            String::from(CONFIG_WINDOWS_PATH)
×
558
        }
559
    }else{
560
        let default_path: String = format!("{}/config/{}/config.yml", current_dir, system);
2✔
561
        let relative_path: String = format!("{}/../../config/{}/config.yml", current_dir, system);
2✔
562
        if Path::new(default_path.as_str()).exists() {
3✔
563
            default_path
1✔
564
        }else if Path::new(&format!("{}/config.yml", current_dir)).exists() {
×
565
            format!("{}/config.yml", current_dir)
×
566
        }else if Path::new(relative_path.as_str()).exists() {
×
567
            relative_path
×
568
        }else if system == "macos" {
×
569
            String::from(CONFIG_MACOS_PATH)
×
570
        }else{
571
            String::from(CONFIG_LINUX_PATH)
×
572
        } 
573
    }
574
}
575

576
// ----------------------------------------------------------------------------
577

578
#[cfg(test)]
579
mod tests {
580
    use super::*;
581

582
    // ------------------------------------------------------------------------
583

584
    pub fn create_test_config(filter: &str, events_destination: &str) -> AppConfig {
585
        AppConfig {
586
            version: String::from(VERSION),
587
            path: String::from("test"),
588
            events_watcher: String::from("Recommended"),
589
            events_destination: String::from(events_destination),
590
            events_max_file_checksum: 64,
591
            events_max_file_size: 128,
592
            checksum_algorithm: ShaType::Sha512,
593
            endpoint_type: String::from("Elastic"),
594
            endpoint_address: String::from("test"),
595
            endpoint_user: String::from("test"),
596
            endpoint_pass: String::from("test"),
597
            endpoint_token: String::from("test"),
598
            events_file: String::from("test"),
599
            monitor: Array::new(),
600
            audit: Array::new(),
601
            node: String::from("test"),
602
            log_file: String::from("./test.log"),
603
            log_level: String::from(filter),
604
            log_max_file_size: 64,
605
            system: String::from("test"),
606
            insecure: true,
607
            events_lock: Arc::new(Mutex::new(false)),
608
            log_lock: Arc::new(Mutex::new(false)),
609
            hashscanner_file: String::from("test"),
610
            hashscanner_enabled: true,
611
            hashscanner_interval: 3600,
612
            hashscanner_algorithm: ShaType::Sha256,
613
            engine: String::from("monitor")
614
        }
615
    }
616

617
    // ------------------------------------------------------------------------
618

619
    #[test]
620
    fn test_clone() {
621
        let cfg = create_test_config("info", "");
622
        let cloned = cfg.clone();
623
        assert_eq!(cfg.version, cloned.version);
624
        assert_eq!(cfg.path, cloned.path);
625
        assert_eq!(cfg.events_destination, cloned.events_destination);
626
        assert_eq!(cfg.events_max_file_checksum, cloned.events_max_file_checksum);
627
        assert_eq!(cfg.events_max_file_size, cloned.events_max_file_size);
628
        assert_eq!(cfg.endpoint_type, cloned.endpoint_type);
629
        assert_eq!(cfg.endpoint_address, cloned.endpoint_address);
630
        assert_eq!(cfg.endpoint_user, cloned.endpoint_user);
631
        assert_eq!(cfg.endpoint_pass, cloned.endpoint_pass);
632
        assert_eq!(cfg.endpoint_token, cloned.endpoint_token);
633
        assert_eq!(cfg.events_file, cloned.events_file);
634
        assert_eq!(cfg.monitor, cloned.monitor);
635
        assert_eq!(cfg.audit, cloned.audit);
636
        assert_eq!(cfg.node, cloned.node);
637
        assert_eq!(cfg.log_file, cloned.log_file);
638
        assert_eq!(cfg.log_level, cloned.log_level);
639
        assert_eq!(cfg.log_max_file_size, cloned.log_max_file_size);
640
        assert_eq!(cfg.system, cloned.system);
641
        assert_eq!(cfg.insecure, cloned.insecure);
642
        assert_eq!(cfg.hashscanner_file, cloned.hashscanner_file);
643
        assert_eq!(cfg.hashscanner_enabled, cloned.hashscanner_enabled);
644
        assert_eq!(cfg.hashscanner_interval, cloned.hashscanner_interval);
645
        assert_eq!(cfg.hashscanner_algorithm, cloned.hashscanner_algorithm);
646
        assert_eq!(cfg.engine, cloned.engine);
647
    }
648

649
    // ------------------------------------------------------------------------
650

651
    #[cfg(target_os = "windows")]
652
    #[test]
653
    fn test_new_config_windows() {
654
        let dir = utils::get_current_dir();
655
        let disk = dir.get(0..1).unwrap();
656
        let cfg = AppConfig::new("windows", None);
657

658
        assert_eq!(cfg.version, String::from(VERSION));
659
        assert_eq!(cfg.events_destination, String::from("file"));
660
        assert_eq!(cfg.endpoint_address, String::from("Not_defined"));
661
        assert_eq!(cfg.endpoint_type, String::from("Not_defined"));
662
        assert_eq!(cfg.endpoint_user, String::from("Not_defined"));
663
        assert_eq!(cfg.endpoint_pass, String::from("Not_defined"));
664
        assert_eq!(cfg.endpoint_token, String::from("Not_defined"));
665
        assert_eq!(cfg.events_file, format!("{}:\\ProgramData\\fim\\events.json", disk) );
666
        // monitor
667
        // audit
668
        assert_eq!(cfg.node, String::from("FIM"));
669
        assert_eq!(cfg.log_file, format!("{}:\\ProgramData\\fim\\fim.log", disk) );
670
        assert_eq!(cfg.log_level, String::from("info"));
671
        assert_eq!(cfg.log_max_file_size, 64);
672
        assert_eq!(cfg.system, String::from("windows"));
673
        assert_eq!(cfg.insecure, false);
674
        assert_eq!(cfg.hashscanner_file, format!("{}:\\ProgramData\\fim\\fim.db", disk) );
675
        assert_eq!(cfg.hashscanner_enabled, true);
676
        assert_eq!(cfg.hashscanner_interval, 3600);
677
        assert_eq!(cfg.hashscanner_algorithm, ShaType::Sha256);
678
        assert_eq!(cfg.engine, String::from("monitor"));
679
    }
680

681
    // ------------------------------------------------------------------------
682

683
    #[cfg(target_os = "windows")]
684
    #[test]
685
    fn test_new_config_windows_events_destination() {
686
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_destination_none.yml"));
687
        assert_eq!(cfg.events_destination, String::from("file"));
688
    }
689

690
    // ------------------------------------------------------------------------
691

692
    #[cfg(target_os = "windows")]
693
    #[test]
694
    #[should_panic]
695
    fn test_new_config_windows_hashscanner_file() {
696
        AppConfig::new("windows", Some("test/unit/config/windows/hashscanner_file_none.yml"));
697
    }
698

699
    // ------------------------------------------------------------------------
700

701
    #[cfg(target_os = "windows")]
702
    #[test]
703
    #[should_panic]
704
    fn test_new_config_windows_events_file() {
705
        AppConfig::new("windows", Some("test/unit/config/windows/events_file_none.yml"));
706
    }
707

708
    // ------------------------------------------------------------------------
709

710
    #[cfg(target_os = "windows")]
711
    #[test]
712
    fn test_new_config_windows_events_destination_network() {
713
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_destination_network.yml"));
714
        assert_eq!(cfg.events_file, String::from("Not_defined"));
715
    }
716

717
    // ------------------------------------------------------------------------
718

719
    #[cfg(target_os = "windows")]
720
    #[test]
721
    fn test_new_config_windows_events_max_file_checksum() {
722
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_max_file_checksum.yml"));
723
        assert_eq!(cfg.events_max_file_checksum, 128);
724
    }
725

726
    // ------------------------------------------------------------------------
727

728
    #[cfg(target_os = "windows")]
729
    #[test]
730
    fn test_new_config_windows_events_max_file_size() {
731
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_max_file_size.yml"));
732
        assert_eq!(cfg.events_max_file_size, 256);
733
    }
734

735
    // ------------------------------------------------------------------------
736

737
    #[cfg(target_os = "windows")]
738
    #[test]
739
    fn test_new_config_windows_events_endpoint_insecure() {
740
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_endpoint_insecure.yml"));
741
        assert_eq!(cfg.insecure, true);
742
    }
743

744
    // ------------------------------------------------------------------------
745

746
    #[cfg(target_os = "windows")]
747
    #[test]
748
    fn test_new_config_windows_events_endpoint_insecure_none() {
749
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_endpoint_insecure_none.yml"));
750
        assert_eq!(cfg.insecure, false);
751
    }
752

753
    // ------------------------------------------------------------------------
754

755
    #[cfg(target_os = "windows")]
756
    #[test]
757
    fn test_new_config_windows_events_destination_network_address() {
758
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_destination_network_address.yml"));
759
        assert_eq!(cfg.endpoint_address, "0.0.0.0");
760
    }
761

762
    // ------------------------------------------------------------------------
763

764
    #[cfg(target_os = "windows")]
765
    #[test]
766
    #[should_panic]
767
    fn test_new_config_windows_events_destination_network_address_none() {
768
        AppConfig::new("windows", Some("test/unit/config/windows/events_destination_network_address_none.yml"));
769
    }
770

771
    // ------------------------------------------------------------------------
772

773
    #[cfg(target_os = "windows")]
774
    #[test]
775
    fn test_new_config_windows_events_credentials_user() {
776
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_credentials_user.yml"));
777
        assert_eq!(cfg.endpoint_user, "test_user");
778
    }
779

780
    // ------------------------------------------------------------------------
781

782
    #[cfg(target_os = "windows")]
783
    #[test]
784
    #[should_panic]
785
    fn test_new_config_windows_events_credentials_user_none() {
786
        AppConfig::new("windows", Some("test/unit/config/windows/events_credentials_user_none.yml"));
787
    }
788

789
    // ------------------------------------------------------------------------
790

791
    #[cfg(target_os = "windows")]
792
    #[test]
793
    fn test_new_config_windows_events_credentials_password() {
794
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_credentials_password.yml"));
795
        assert_eq!(cfg.endpoint_pass, "test_password");
796
    }
797

798
    // ------------------------------------------------------------------------
799

800
    #[cfg(target_os = "windows")]
801
    #[test]
802
    fn test_new_config_windows_events_credentials_token() {
803
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_credentials_token.yml"));
804
        assert_eq!(cfg.endpoint_token, "test_token");
805
    }
806

807
    // ------------------------------------------------------------------------
808

809
    #[cfg(target_os = "windows")]
810
    #[test]
811
    #[should_panic]
812
    fn test_new_config_windows_events_credentials_password_none() {
813
        AppConfig::new("windows", Some("test/unit/config/windows/events_credentials_password_none.yml"));
814
    }
815

816
    // ------------------------------------------------------------------------
817

818
    #[cfg(target_os = "windows")]
819
    #[test]
820
    #[should_panic]
821
    fn test_new_config_windows_monitor_none() {
822
        AppConfig::new("windows", Some("test/unit/config/windows/monitor_none.yml"));
823
    }
824

825
    // ------------------------------------------------------------------------
826

827
    #[cfg(target_os = "windows")]
828
    #[test]
829
    fn test_new_config_windows_node_none() {
830
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/node_none.yml"));
831
        assert_eq!(cfg.node, utils::get_hostname());
832
    }
833

834
    // ------------------------------------------------------------------------
835

836
    #[cfg(target_os = "windows")]
837
    #[test]
838
    #[should_panic]
839
    fn test_new_config_windows_log_file_none() {
840
        AppConfig::new("windows", Some("test/unit/config/windows/log_file_none.yml"));
841
    }
842

843
    // ------------------------------------------------------------------------
844

845
    #[cfg(target_os = "windows")]
846
    #[test]
847
    fn test_new_config_windows_log_level_none() {
848
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/log_level_none.yml"));
849
        assert_eq!(cfg.log_level, "info");
850
    }
851

852
    // ------------------------------------------------------------------------
853

854
    #[cfg(target_os = "windows")]
855
    #[test]
856
    fn test_new_config_windows_log_max_file_size_none() {
857
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/log_max_file_size_none.yml"));
858
        assert_eq!(cfg.log_max_file_size, 64);
859
    }
860

861
    // ------------------------------------------------------------------------
862

863
    #[cfg(target_os = "linux")]
864
    #[test]
865
    fn test_new_config_linux_events_destination() {
866
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_destination_none.yml"));
867
        assert_eq!(cfg.events_destination, String::from("file"));
868
    }
869

870
    // ------------------------------------------------------------------------
871

872
    #[cfg(target_os = "linux")]
873
    #[test]
874
    #[should_panic]
875
    fn test_new_config_linux_hashscanner_file() {
876
        AppConfig::new("linux", Some("test/unit/config/linux/hashscanner_file_none.yml"));
877
    }
878

879
    // ------------------------------------------------------------------------
880

881
    #[cfg(target_os = "linux")]
882
    #[test]
883
    #[should_panic]
884
    fn test_new_config_linux_events_file() {
885
        AppConfig::new("linux", Some("test/unit/config/linux/events_file_none.yml"));
886
    }
887

888
    // ------------------------------------------------------------------------
889

890
    #[cfg(target_os = "linux")]
891
    #[test]
892
    fn test_new_config_linux_events_destination_network() {
893
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_destination_network.yml"));
894
        assert_eq!(cfg.events_file, String::from("Not_defined"));
895
    }
896

897
    // ------------------------------------------------------------------------
898

899
    #[cfg(target_os = "linux")]
900
    #[test]
901
    fn test_new_config_linux_events_max_file_checksum() {
902
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_max_file_checksum.yml"));
903
        assert_eq!(cfg.events_max_file_checksum, 128);
904
    }
905

906
    // ------------------------------------------------------------------------
907

908
    #[cfg(target_os = "linux")]
909
    #[test]
910
    fn test_new_config_linux_events_max_file_size() {
911
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_max_file_size.yml"));
912
        assert_eq!(cfg.events_max_file_size, 256);
913
    }
914

915
    // ------------------------------------------------------------------------
916

917
    #[cfg(target_os = "linux")]
918
    #[test]
919
    fn test_new_config_linux_events_endpoint_insecure() {
920
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_endpoint_insecure.yml"));
921
        assert_eq!(cfg.insecure, true);
922
    }
923

924
    // ------------------------------------------------------------------------
925

926
    #[cfg(target_os = "linux")]
927
    #[test]
928
    fn test_new_config_linux_events_endpoint_insecure_none() {
929
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_endpoint_insecure_none.yml"));
930
        assert_eq!(cfg.insecure, false);
931
    }
932

933
    // ------------------------------------------------------------------------
934

935
    #[cfg(target_os = "linux")]
936
    #[test]
937
    fn test_new_config_linux_events_destination_network_address() {
938
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_destination_network_address.yml"));
939
        assert_eq!(cfg.endpoint_address, "0.0.0.0");
940
    }
941

942
    // ------------------------------------------------------------------------
943

944
    #[cfg(target_os = "linux")]
945
    #[test]
946
    #[should_panic]
947
    fn test_new_config_linux_events_destination_network_address_none() {
948
        AppConfig::new("linux", Some("test/unit/config/linux/events_destination_network_address_none.yml"));
949
    }
950

951
    // ------------------------------------------------------------------------
952

953
    #[cfg(target_os = "linux")]
954
    #[test]
955
    fn test_new_config_linux_events_credentials_user() {
956
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_credentials_user.yml"));
957
        assert_eq!(cfg.endpoint_user, "test_user");
958
    }
959

960
    // ------------------------------------------------------------------------
961

962
    #[cfg(target_os = "linux")]
963
    #[test]
964
    #[should_panic]
965
    fn test_new_config_linux_events_credentials_user_none() {
966
        AppConfig::new("linux", Some("test/unit/config/linux/events_credentials_user_none.yml"));
967
    }
968

969
    // ------------------------------------------------------------------------
970

971
    #[cfg(target_os = "linux")]
972
    #[test]
973
    fn test_new_config_linux_events_credentials_password() {
974
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_credentials_password.yml"));
975
        assert_eq!(cfg.endpoint_pass, "test_password");
976
    }
977

978
    // ------------------------------------------------------------------------
979

980
    #[cfg(target_os = "linux")]
981
    #[test]
982
    fn test_new_config_linux_events_credentials_token() {
983
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/events_credentials_token.yml"));
984
        assert_eq!(cfg.endpoint_token, "test_token");
985
    }
986

987
    // ------------------------------------------------------------------------
988

989
    #[cfg(target_os = "linux")]
990
    #[test]
991
    #[should_panic]
992
    fn test_new_config_linux_events_credentials_password_none() {
993
        AppConfig::new("linux", Some("test/unit/config/linux/events_credentials_password_none.yml"));
994
    }
995

996
    // ------------------------------------------------------------------------
997

998
    #[cfg(target_os = "linux")]
999
    #[test]
1000
    fn test_new_config_linux_monitor_none() {
1001
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/monitor_none.yml"));
1002
        assert_eq!(cfg.monitor, Vec::new());
1003
    }
1004

1005
    // ------------------------------------------------------------------------
1006

1007
    #[cfg(target_os = "linux")]
1008
    #[test]
1009
    fn test_new_config_linux_audit_none() {
1010
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/audit_none.yml"));
1011
        assert_eq!(cfg.audit, Vec::new());
1012
    }
1013

1014
    // ------------------------------------------------------------------------
1015

1016
    #[cfg(target_os = "linux")]
1017
    #[test]
1018
    #[should_panic]
1019
    fn test_new_config_linux_audit_and_monitor_none() {
1020
        AppConfig::new("linux", Some("test/unit/config/linux/audit_and_monitor_none.yml"));
1021
    }
1022

1023
    // ------------------------------------------------------------------------
1024

1025
    #[cfg(target_os = "linux")]
1026
    #[test]
1027
    fn test_new_config_linux_node_none() {
1028
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/node_none.yml"));
1029
        let machine_id = utils::get_machine_id();
1030
        match machine_id.is_empty(){
1031
            true => assert_eq!(cfg.node, utils::get_hostname()),
1032
            false => assert_eq!(cfg.node, machine_id)
1033
        }
1034
    }
1035

1036
    // ------------------------------------------------------------------------
1037

1038
    #[cfg(target_os = "linux")]
1039
    #[test]
1040
    #[should_panic]
1041
    fn test_new_config_linux_log_file_none() {
1042
        AppConfig::new("linux", Some("test/unit/config/linux/log_file_none.yml"));
1043
    }
1044

1045
    // ------------------------------------------------------------------------
1046

1047
    #[cfg(target_os = "linux")]
1048
    #[test]
1049
    fn test_new_config_linux_log_level_none() {
1050
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/log_level_none.yml"));
1051
        assert_eq!(cfg.log_level, "info");
1052
    }
1053

1054
    // ------------------------------------------------------------------------
1055

1056
    #[cfg(target_os = "linux")]
1057
    #[test]
1058
    fn test_new_config_linux_log_max_file_size_none() {
1059
        let cfg = AppConfig::new("linux", Some("test/unit/config/linux/log_max_file_size_none.yml"));
1060
        assert_eq!(cfg.log_max_file_size, 64);
1061
    }
1062

1063
    // ------------------------------------------------------------------------
1064

1065
    #[cfg(target_os = "linux")]
1066
    #[test]
1067
    fn test_new_config_linux() {
1068
        if utils::get_os() == "linux" {
1069
            let cfg = AppConfig::new("linux", None);
1070
            assert_eq!(cfg.version, String::from(VERSION));
1071
            assert_eq!(cfg.events_destination, String::from("file"));
1072
            assert_eq!(cfg.endpoint_type, String::from("Not_defined"));
1073
            assert_eq!(cfg.endpoint_address, String::from("Not_defined"));
1074
            assert_eq!(cfg.endpoint_user, String::from("Not_defined"));
1075
            assert_eq!(cfg.endpoint_pass, String::from("Not_defined"));
1076
            assert_eq!(cfg.endpoint_token, String::from("Not_defined"));
1077
            assert_eq!(cfg.events_file, String::from("/var/lib/fim/events.json"));
1078
            // monitor
1079
            // audit
1080
            assert_eq!(cfg.node, String::from("FIM"));
1081
            assert_eq!(cfg.log_file, String::from("/var/log/fim/fim.log"));
1082
            assert_eq!(cfg.log_level, String::from("info"));
1083
            assert_eq!(cfg.log_max_file_size, 64);
1084
            assert_eq!(cfg.system, String::from("linux"));
1085
            assert_eq!(cfg.insecure, false);
1086
            assert_eq!(cfg.hashscanner_file, String::from("/var/lib/fim/fim.db"));
1087
            assert_eq!(cfg.hashscanner_enabled, true);
1088
            assert_eq!(cfg.hashscanner_interval, 3600);
1089
            assert_eq!(cfg.hashscanner_algorithm, ShaType::Sha256);
1090
            assert_eq!(cfg.engine, String::from("monitor"));
1091
        }
1092
    }
1093

1094
    // ------------------------------------------------------------------------
1095

1096
    #[cfg(target_os = "macos")]
1097
    #[test]
1098
    fn test_new_config_macos() {
1099
        let cfg = AppConfig::new("macos", None);
1100
        assert_eq!(cfg.version, String::from(VERSION));
1101
        assert_eq!(cfg.events_destination, String::from("file"));
1102
        assert_eq!(cfg.endpoint_type, String::from("Not_defined"));
1103
        assert_eq!(cfg.endpoint_address, String::from("Not_defined"));
1104
        assert_eq!(cfg.endpoint_user, String::from("Not_defined"));
1105
        assert_eq!(cfg.endpoint_pass, String::from("Not_defined"));
1106
        assert_eq!(cfg.endpoint_token, String::from("Not_defined"));
1107
        assert_eq!(cfg.events_file, String::from("/var/lib/fim/events.json"));
1108
        // monitor
1109
        // audit
1110
        assert_eq!(cfg.node, String::from("FIM"));
1111
        assert_eq!(cfg.log_file, String::from("/var/log/fim/fim.log"));
1112
        assert_eq!(cfg.log_level, String::from("info"));
1113
        assert_eq!(cfg.log_max_file_size, 64);
1114
        assert_eq!(cfg.system, String::from("macos"));
1115
        assert_eq!(cfg.insecure, false);
1116
        assert_eq!(cfg.hashscanner_file, String::from("/var/lib/fim/fim.db"));
1117
        assert_eq!(cfg.hashscanner_enabled, true);
1118
        assert_eq!(cfg.hashscanner_interval, 3600);
1119
        assert_eq!(cfg.hashscanner_algorithm, ShaType::Sha256);
1120
        assert_eq!(cfg.engine, String::from("monitor"));
1121
    }
1122

1123
    // ------------------------------------------------------------------------
1124

1125
    #[test]
1126
    fn test_get_level_filter_info() {
1127
        let filter = LevelFilter::Info;
1128
        assert_eq!(create_test_config("info", "").get_level_filter(), filter);
1129
        assert_eq!(create_test_config("Info", "").get_level_filter(), filter);
1130
        assert_eq!(create_test_config("INFO", "").get_level_filter(), filter);
1131
        assert_eq!(create_test_config("I", "").get_level_filter(), filter);
1132
        assert_eq!(create_test_config("i", "").get_level_filter(), filter);
1133
    }
1134

1135
    // ------------------------------------------------------------------------
1136

1137
    #[test]
1138
    fn test_get_level_filter_debug() {
1139
        let filter = LevelFilter::Debug;
1140
        assert_eq!(create_test_config("debug", "").get_level_filter(), filter);
1141
        assert_eq!(create_test_config("Debug", "").get_level_filter(), filter);
1142
        assert_eq!(create_test_config("DEBUG", "").get_level_filter(), filter);
1143
        assert_eq!(create_test_config("D", "").get_level_filter(), filter);
1144
        assert_eq!(create_test_config("d", "").get_level_filter(), filter);
1145
    }
1146

1147
    // ------------------------------------------------------------------------
1148

1149
    #[test]
1150
    fn test_get_level_filter_error() {
1151
        let filter = LevelFilter::Error;
1152
        assert_eq!(create_test_config("error", "").get_level_filter(), filter);
1153
        assert_eq!(create_test_config("Error", "").get_level_filter(), filter);
1154
        assert_eq!(create_test_config("ERROR", "").get_level_filter(), filter);
1155
        assert_eq!(create_test_config("E", "").get_level_filter(), filter);
1156
        assert_eq!(create_test_config("e", "").get_level_filter(), filter);
1157
    }
1158

1159
    // ------------------------------------------------------------------------
1160

1161
    #[test]
1162
    fn test_get_level_filter_warning() {
1163
        let filter = LevelFilter::Warn;
1164
        assert_eq!(create_test_config("warning", "").get_level_filter(), filter);
1165
        assert_eq!(create_test_config("Warning", "").get_level_filter(), filter);
1166
        assert_eq!(create_test_config("WARNING", "").get_level_filter(), filter);
1167
        assert_eq!(create_test_config("W", "").get_level_filter(), filter);
1168
        assert_eq!(create_test_config("w", "").get_level_filter(), filter);
1169
        assert_eq!(create_test_config("warn", "").get_level_filter(), filter);
1170
        assert_eq!(create_test_config("Warn", "").get_level_filter(), filter);
1171
        assert_eq!(create_test_config("WARN", "").get_level_filter(), filter);
1172
    }
1173

1174
    // ------------------------------------------------------------------------
1175

1176
    #[test]
1177
    fn test_get_level_filter_bad() {
1178
        let filter = LevelFilter::Info;
1179
        assert_eq!(create_test_config("bad", "").get_level_filter(), filter);
1180
        assert_eq!(create_test_config("BAD", "").get_level_filter(), filter);
1181
        assert_eq!(create_test_config("B", "").get_level_filter(), filter);
1182
        assert_eq!(create_test_config("b", "").get_level_filter(), filter);
1183
        assert_eq!(create_test_config("test", "").get_level_filter(), filter);
1184
        assert_eq!(create_test_config("", "").get_level_filter(), filter);
1185
        assert_eq!(create_test_config("_", "").get_level_filter(), filter);
1186
        assert_eq!(create_test_config("?", "").get_level_filter(), filter);
1187
        assert_eq!(create_test_config("=", "").get_level_filter(), filter);
1188
        assert_eq!(create_test_config("/", "").get_level_filter(), filter);
1189
        assert_eq!(create_test_config(".", "").get_level_filter(), filter);
1190
        assert_eq!(create_test_config(":", "").get_level_filter(), filter);
1191
        assert_eq!(create_test_config(";", "").get_level_filter(), filter);
1192
        assert_eq!(create_test_config("!", "").get_level_filter(), filter);
1193
        assert_eq!(create_test_config("''", "").get_level_filter(), filter);
1194
        assert_eq!(create_test_config("[]", "").get_level_filter(), filter);
1195
    }
1196

1197
    // ------------------------------------------------------------------------
1198

1199
    #[test]
1200
    fn test_get_events_destination() {
1201
        assert_eq!(create_test_config("info", "both").get_events_destination(), String::from(BOTH_MODE));
1202
        assert_eq!(create_test_config("info", "network").get_events_destination(), String::from(NETWORK_MODE));
1203
        assert_eq!(create_test_config("info", "file").get_events_destination(), String::from(FILE_MODE));
1204
        assert_eq!(create_test_config("info", "").get_events_destination(), String::from(FILE_MODE));
1205
        assert_eq!(create_test_config("info", "?").get_events_destination(), String::from(FILE_MODE));
1206
    }
1207

1208
    // ------------------------------------------------------------------------
1209

1210
    #[test]
1211
    fn test_read_config_unix() {
1212
        let yaml = read_config(String::from("config/linux/config.yml"));
1213

1214
        assert_eq!(yaml[0]["node"].as_str().unwrap(), "FIM");
1215
        assert_eq!(yaml[0]["events"]["destination"].as_str().unwrap(), "file");
1216
        assert_eq!(yaml[0]["events"]["file"].as_str().unwrap(), "/var/lib/fim/events.json");
1217

1218
        assert_eq!(yaml[0]["monitor"][0]["path"].as_str().unwrap(), "/bin/");
1219
        assert_eq!(yaml[0]["monitor"][1]["path"].as_str().unwrap(), "/usr/bin/");
1220
        assert_eq!(yaml[0]["monitor"][1]["labels"][0].as_str().unwrap(), "usr/bin");
1221
        assert_eq!(yaml[0]["monitor"][1]["labels"][1].as_str().unwrap(), "linux");
1222
        assert_eq!(yaml[0]["monitor"][2]["path"].as_str().unwrap(), "/etc");
1223
        assert_eq!(yaml[0]["monitor"][2]["labels"][0].as_str().unwrap(), "etc");
1224
        assert_eq!(yaml[0]["monitor"][2]["labels"][1].as_str().unwrap(), "linux");
1225

1226
        assert_eq!(yaml[0]["log"]["file"].as_str().unwrap(), "/var/log/fim/fim.log");
1227
        assert_eq!(yaml[0]["log"]["level"].as_str().unwrap(), "info");
1228
    }
1229

1230
    // ------------------------------------------------------------------------
1231

1232
    #[cfg(target_os = "windows")]
1233
    #[test]
1234
    fn test_read_config_windows() {
1235
        let dir = utils::get_current_dir();
1236
        let disk = dir.get(0..1).unwrap();
1237
        let yaml = read_config(String::from("config/windows/config.yml"));
1238

1239
        assert_eq!(yaml[0]["node"].as_str().unwrap(), "FIM");
1240
        assert_eq!(yaml[0]["events"]["destination"].as_str().unwrap(), "file");
1241
        assert_eq!(yaml[0]["events"]["file"].as_str().unwrap(), format!("{}:\\ProgramData\\fim\\events.json", disk) );
1242

1243
        assert_eq!(yaml[0]["monitor"][0]["path"].as_str().unwrap(), "C:\\Program Files\\");
1244
        assert_eq!(yaml[0]["monitor"][0]["labels"][0].as_str().unwrap(), "Program Files");
1245
        assert_eq!(yaml[0]["monitor"][0]["labels"][1].as_str().unwrap(), "windows");
1246
        assert_eq!(yaml[0]["monitor"][1]["path"].as_str().unwrap(), "C:\\Users\\" );
1247
        assert_eq!(yaml[0]["monitor"][1]["labels"][0].as_str().unwrap(), "Users");
1248
        assert_eq!(yaml[0]["monitor"][1]["labels"][1].as_str().unwrap(), "windows");
1249

1250
        assert_eq!(yaml[0]["log"]["file"].as_str().unwrap(), format!("{}:\\ProgramData\\fim\\fim.log", disk) );
1251
        assert_eq!(yaml[0]["log"]["level"].as_str().unwrap(), "info");
1252
    }
1253

1254
    // ------------------------------------------------------------------------
1255

1256
    #[test]
1257
    #[should_panic(expected = "NotFound")]
1258
    fn test_read_config_panic() {
1259
        read_config(String::from("NotFound"));
1260
    }
1261

1262
    // ------------------------------------------------------------------------
1263

1264
    #[test]
1265
    #[should_panic(expected = "ScanError")]
1266
    fn test_read_config_panic_not_config() {
1267
        read_config(String::from("README.md"));
1268
    }
1269

1270
    // ------------------------------------------------------------------------
1271

1272
    #[cfg(not(target_os = "windows"))]
1273
    #[test]
1274
    fn test_get_config_path_unix() {
1275
        let current_dir = utils::get_current_dir();
1276
        let default_path_linux = format!("{}/config/linux/config.yml", current_dir);
1277
        let default_path_macos = format!("{}/config/macos/config.yml", current_dir);
1278
        assert_eq!(get_config_path("linux"), default_path_linux);
1279
        assert_eq!(get_config_path("macos"), default_path_macos);
1280
    }
1281

1282
    // ------------------------------------------------------------------------
1283

1284
    #[cfg(target_os = "windows")]
1285
    #[test]
1286
    fn test_get_config_path_windows() {
1287
        let current_dir = utils::get_current_dir();
1288
        let default_path_windows = format!("{}\\config\\windows\\config.yml", current_dir);
1289
        assert_eq!(get_config_path("windows"), default_path_windows);
1290
    }
1291

1292
    // ------------------------------------------------------------------------
1293

1294
    #[cfg(target_os = "linux")]
1295
    #[test]
1296
    fn test_path_in_monitor() {
1297
        let cfg = AppConfig::new(&utils::get_os(), None);
1298
        assert!(cfg.path_in("/bin/", "", cfg.monitor.clone()));
1299
        assert!(cfg.path_in("/bin", "", cfg.monitor.clone()));
1300
        assert!(cfg.path_in("/bin/test", "", cfg.monitor.clone()));
1301
        assert!(!cfg.path_in("/test", "", cfg.monitor.clone()));
1302
    }
1303

1304
    // ------------------------------------------------------------------------
1305

1306
    #[cfg(target_os = "linux")]
1307
    #[test]
1308
    fn test_path_in_audit() {
1309
        let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/audit_allowed.yml"));
1310
        assert!(cfg.path_in("/tmp", "", cfg.audit.clone()));
1311
        assert!(cfg.path_in("/tmp/", "", cfg.audit.clone()));
1312
        assert!(cfg.path_in("./", "/tmp", cfg.audit.clone()));
1313
        assert!(cfg.path_in("./", "/tmp/", cfg.audit.clone()));
1314
        assert!(!cfg.path_in("./", "/test", cfg.audit.clone()));
1315
        assert!(cfg.path_in("./", "/tmp/test", cfg.audit.clone()));
1316
    }
1317

1318
    // ------------------------------------------------------------------------
1319

1320
    #[cfg(target_os = "linux")]
1321
    #[test]
1322
    fn test_get_index_monitor() {
1323
        let cfg = AppConfig::new(&utils::get_os(), None);
1324
        assert_eq!(cfg.get_index("/bin/", "", cfg.monitor.clone()), 0);
1325
        assert_eq!(cfg.get_index("./", "/bin", cfg.monitor.clone()), 0);
1326
        assert_eq!(cfg.get_index("/usr/bin/", "", cfg.monitor.clone()), 1);
1327
        assert_eq!(cfg.get_index("/etc", "", cfg.monitor.clone()), 2);
1328
        assert_eq!(cfg.get_index("/test", "", cfg.monitor.clone()), usize::MAX);
1329
        assert_eq!(cfg.get_index("./", "/test", cfg.monitor.clone()), usize::MAX);
1330
    }
1331

1332
    // ------------------------------------------------------------------------
1333

1334
    #[cfg(target_os = "linux")]
1335
    #[test]
1336
    fn test_get_index_audit() {
1337
        let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/audit_allowed.yml"));
1338
        assert_eq!(cfg.get_index("/tmp", "", cfg.audit.clone()), 0);
1339
        assert_eq!(cfg.get_index("/test", "", cfg.audit.clone()), usize::MAX);
1340
        assert_eq!(cfg.get_index("./", "/tmp", cfg.audit.clone()), 0);
1341
        assert_eq!(cfg.get_index("./", "/test", cfg.audit.clone()), usize::MAX);
1342
    }
1343

1344
    // ------------------------------------------------------------------------
1345

1346
    #[test]
1347
    fn test_get_labels() {
1348
        let cfg = AppConfig::new(&utils::get_os(), None);
1349
        if utils::get_os() == "windows" {
1350
            let labels = cfg.get_labels(0, cfg.monitor.clone());
1351
            assert_eq!(labels[0], "Program Files");
1352
            assert_eq!(labels[1], "windows");
1353
        }else if utils::get_os() == "macos"{
1354
            let labels = cfg.get_labels(2, cfg.monitor.clone());
1355
            assert_eq!(labels[0], "usr/bin");
1356
            assert_eq!(labels[1], "macos");
1357
        }else{
1358
            let labels = cfg.get_labels(1, cfg.monitor.clone());
1359
            assert_eq!(labels[0], "usr/bin");
1360
            assert_eq!(labels[1], "linux");
1361
        }
1362
    }
1363

1364
    // ------------------------------------------------------------------------
1365

1366
    #[cfg(target_os = "linux")]
1367
    #[test]
1368
    fn test_match_ignore_monitor() {
1369
        let cfg = AppConfig::new(&utils::get_os(), None);
1370
        assert!(cfg.match_ignore(3, "file.swp", cfg.monitor.clone()));
1371
        assert!(!cfg.match_ignore(0, "file.txt", cfg.monitor.clone()));
1372
    }
1373

1374
    // ------------------------------------------------------------------------
1375

1376
    #[cfg(target_os = "linux")]
1377
    #[test]
1378
    fn test_match_ignore_audit() {
1379
        let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/audit_exclude.yml"));
1380
        assert!(cfg.match_ignore(0, "file.swp", cfg.audit.clone()));
1381
        assert!(!cfg.match_ignore(0, "file.txt", cfg.audit.clone()));
1382
    }
1383

1384
    // ------------------------------------------------------------------------
1385

1386
    #[cfg(target_os = "linux")]
1387
    #[test]
1388
    fn test_match_exclude() {
1389
        let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/audit_exclude.yml"));
1390
        assert!(cfg.match_exclude(0, "/tmp/test", cfg.audit.clone()));
1391
        assert!(!cfg.match_exclude(0, "/tmp/another", cfg.audit.clone()));
1392
    }
1393

1394
    // ------------------------------------------------------------------------
1395

1396
    #[test]
1397
    fn test_match_allowed() {
1398
        if utils::get_os() == "windows" {
1399
            let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/windows/monitor_allowed.yml"));
1400
            assert!(!cfg.match_allowed(1, "file.swp", cfg.monitor.clone()));
1401
            assert!(cfg.match_allowed(1, "file.txt", cfg.monitor.clone()));
1402
        } else if utils::get_os() == "linux" {
1403
            let cfg = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/monitor_allowed.yml"));
1404
            assert!(!cfg.match_allowed(2, "file.swp", cfg.monitor.clone()));
1405
            assert!(cfg.match_allowed(2, "file.txt", cfg.monitor.clone()));
1406

1407
            let cfg_audit = AppConfig::new(&utils::get_os(), Some("test/unit/config/linux/audit_allowed.yml"));
1408
            assert!(!cfg_audit.match_allowed(0, "file.swp", cfg_audit.audit.clone()));
1409
            assert!(cfg_audit.match_allowed(0, "file.txt", cfg_audit.audit.clone()));
1410
        }
1411
    }
1412

1413
    // ------------------------------------------------------------------------
1414

1415
    #[test]
1416
    fn test_get_integrations() {
1417
        let os = utils::get_os();
1418
        let cfg = AppConfig::new(&os,
1419
            Some(format!("test/unit/config/{}/monitor_integration.yml", os)
1420
                .as_str())
1421
        );
1422
        if os == "windows" {
1423
            let integrations = cfg.get_integrations(2, cfg.monitor.clone());
1424
            assert_eq!(integrations.len(), 1);
1425
        }else if os == "macos"{
1426
            let integrations = cfg.get_integrations(2, cfg.monitor.clone());
1427
            assert_eq!(integrations.len(), 1);
1428
        }else{
1429
            let integrations_monitor = cfg.get_integrations(2, cfg.monitor.clone());
1430
            assert_eq!(integrations_monitor.len(), 1);
1431

1432
            // Not implemented yet
1433
            //let integrations_audit = cfg.get_integrations(2, cfg.audit.clone());
1434
            //assert_eq!(integrations_audit.len(), 1);
1435
        }
1436
    }
1437

1438
    // ------------------------------------------------------------------------
1439

1440
    #[test]
1441
    fn test_new_config_watcher() {
1442
        let cfg = AppConfig::new("windows", Some("test/unit/config/windows/events_watcher.yml"));
1443
        assert_eq!(cfg.events_watcher, "Poll");
1444
    }
1445

1446
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc