Skip to content

Commit

Permalink
Moved static config to variable passed, included mutex into configura…
Browse files Browse the repository at this point in the history
…tion that replaces static TMP_EVENTS
  • Loading branch information
okynos committed Apr 23, 2024
1 parent a01c68a commit 62898ed
Show file tree
Hide file tree
Showing 14 changed files with 258 additions and 240 deletions.
75 changes: 32 additions & 43 deletions src/auditevent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl Event {
parent["name"].clone(), path["name"].clone()),
config.events_max_file_checksum),
fpid: utils::get_pid(),
system: utils::get_os(),
system: String::from(utils::get_os()),


ogid: get_field(path.clone(), "ogid"),
Expand Down Expand Up @@ -346,27 +346,26 @@ impl Event {
// ------------------------------------------------------------------------

// Function to send events through network
pub async fn send(&self, index: String) {
pub async fn send(&self, index: String, cfg: config::Config) {
let event = self.get_json();
let config = unsafe { super::GCONFIG.clone().unwrap() };

// Splunk endpoint integration
if config.endpoint_type == "Splunk" {
if cfg.endpoint_type == "Splunk" {
let data = json!({
"source": self.node.clone(),
"sourcetype": "_json",
"event": event,
"index": "fim_events"
});
debug!("Sending received event to Splunk integration, event: {}", data);
let request_url = format!("{}/services/collector/event", config.endpoint_address);
let request_url = format!("{}/services/collector/event", cfg.endpoint_address);
let client = Client::builder()
.danger_accept_invalid_certs(config.insecure)
.danger_accept_invalid_certs(cfg.insecure)
.timeout(Duration::from_secs(30))
.build().unwrap();
match client
.post(request_url)
.header("Authorization", format!("Splunk {}", config.endpoint_token))
.header("Authorization", format!("Splunk {}", cfg.endpoint_token))
.json(&data)
.send()
.await {
Expand All @@ -376,14 +375,14 @@ impl Event {
}
// Elastic endpoint integration
} else {
let request_url = format!("{}/{}/_doc/{}", config.endpoint_address, index, self.id);
let request_url = format!("{}/{}/_doc/{}", cfg.endpoint_address, index, self.id);
let client = Client::builder()
.danger_accept_invalid_certs(config.insecure)
.danger_accept_invalid_certs(cfg.insecure)
.timeout(Duration::from_secs(30))
.build().unwrap();
match client
.post(request_url)
.basic_auth(config.endpoint_user, Some(config.endpoint_pass))
.basic_auth(cfg.endpoint_user, Some(cfg.endpoint_pass))
.json(&event)
.send()
.await {
Expand All @@ -397,16 +396,16 @@ impl Event {
// ------------------------------------------------------------------------

// Function to manage event destination
pub async fn process(&self, destination: &str, index_name: String, config: config::Config){
pub async fn process(&self, destination: &str, index_name: String, cfg: config::Config){
match destination {
config::BOTH_MODE => {
self.log(&config.get_events_file());
self.send(index_name).await;
self.log(&cfg.get_events_file());
self.send(index_name, cfg).await;
},
config::NETWORK_MODE => {
self.send(index_name).await;
self.send(index_name, cfg).await;
},
_ => self.log(&config.get_events_file())
_ => self.log(&cfg.get_events_file())
}
}
}
Expand All @@ -422,26 +421,26 @@ fn get_field(map: HashMap<String, String>,field: &str) -> String {

// ----------------------------------------------------------------------------

pub fn get_parent(paths: Vec<HashMap<String, String>>, cwd: &str, config: config::Config) -> HashMap<String, String> {
pub fn get_parent(paths: Vec<HashMap<String, String>>, cwd: &str, cfg: config::Config) -> HashMap<String, String> {
match paths.iter().find(|p|{
utils::get_field((*p).clone(), "nametype") == "PARENT" &&
config.path_in(p["name"].as_str(), cwd, config.audit.clone())
cfg.path_in(p["name"].as_str(), cwd, cfg.audit.clone())
}){
Some(p) => p.clone(),
None => get_item_path(paths.clone(), cwd, config.clone())
None => get_item_path(paths.clone(), cwd, cfg.clone())
}
}

// ----------------------------------------------------------------------------

pub fn get_item_path(paths: Vec<HashMap<String, String>>, cwd: &str, config: config::Config) -> HashMap<String, String> {
pub fn get_item_path(paths: Vec<HashMap<String, String>>, cwd: &str, cfg: config::Config) -> HashMap<String, String> {
match paths.iter().rfind(|p|{
utils::get_field((*p).clone(), "nametype") != "PARENT" &&
utils::get_field((*p).clone(), "nametype") != "UNKNOWN" &&
config.path_in(p["name"].as_str(), cwd, config.audit.clone())
cfg.path_in(p["name"].as_str(), cwd, cfg.audit.clone())
}){
Some(p) => p.clone(),
None => get_parent(paths.clone(), cwd, config.clone())
None => get_parent(paths.clone(), cwd, cfg.clone())
}
}

Expand Down Expand Up @@ -515,12 +514,6 @@ mod tests {
fs::remove_file(filename).unwrap()
}

fn initialize() {
unsafe{
super::super::GCONFIG = Some(config::Config::new(&utils::get_os(), None));
}
}

fn create_empty_event() -> Event {
Event {
id: String::from(""), timestamp: String::from(""),
Expand Down Expand Up @@ -592,7 +585,7 @@ mod tests {
#[test]
fn test_from() {
if utils::get_os() == "linux" {
let config = Config::new(&utils::get_os(),
let cfg = Config::new(&utils::get_os(),
Some("test/unit/config/linux/audit_from_test.yml"));
let syscall = HashMap::<String, String>::from([
(String::from("syscall"), String::from("syscall")),
Expand Down Expand Up @@ -676,7 +669,7 @@ mod tests {
(String::from("msg"), String::from("audit(1659026449.689:6434)"))
]);

let event = Event::from(syscall.clone(), cwd.clone(), proctitle, paths.clone(), config.clone());
let event = Event::from(syscall.clone(), cwd.clone(), proctitle, paths.clone(), cfg.clone());
assert_eq!(String::from("1659026449689"), event.timestamp);
assert_eq!(utils::get_hostname(), event.hostname);
assert_eq!(String::from("FIM"), event.node);
Expand Down Expand Up @@ -735,7 +728,7 @@ mod tests {
(String::from("proctitle"), String::from("bash")),
(String::from("msg"), String::from("audit(1659026449.689:6434)"))
]);
let event = Event::from(syscall, cwd, proctitle, paths.clone(), config.clone());
let event = Event::from(syscall, cwd, proctitle, paths.clone(), cfg.clone());
assert_eq!(String::from("bash"), event.proctitle);

}
Expand Down Expand Up @@ -946,34 +939,30 @@ mod tests {

#[test]
fn test_send() {
initialize();
let event = create_test_event();
block_on( event.send(String::from("test")) );
let cfg = config::Config::new(&utils::get_os(), None);
block_on( event.send(String::from("test"), cfg) );
}

// ------------------------------------------------------------------------

#[test]
fn test_send_splunk() {
initialize();
let evt = create_test_event();
unsafe {
super::super::GCONFIG = Some(config::Config::new(&utils::get_os(), Some("test/unit/config/common/test_send_splunk.yml")));
}
block_on( evt.send(String::from("test")) );
let event = create_test_event();
let cfg = Config::new(&utils::get_os(), Some("test/unit/config/common/test_send_splunk.yml"));
block_on( event.send(String::from("test"), cfg) );
}

// ------------------------------------------------------------------------

#[test]
fn test_process() {
initialize();
let config = Config::new(&utils::get_os(), None);
let cfg = Config::new(&utils::get_os(), None);
let event = create_test_event();

block_on(event.process(config::NETWORK_MODE, String::from("test"), config.clone()));
block_on(event.process(config::FILE_MODE, String::from("test2"), config.clone()));
block_on(event.process(config::BOTH_MODE, String::from("test3"), config.clone()));
block_on(event.process(config::NETWORK_MODE, String::from("test"), cfg.clone()));
block_on(event.process(config::FILE_MODE, String::from("test2"), cfg.clone()));
block_on(event.process(config::BOTH_MODE, String::from("test3"), cfg.clone()));
}

// ------------------------------------------------------------------------
Expand Down
72 changes: 51 additions & 21 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,21 @@ const CONFIG_MACOS_PATH: &str = "/Applications/FileMonitor.app/config.yml";
const CONFIG_LINUX_PATH: &str = "/etc/fim/config.yml";
const CONFIG_WINDOWS_PATH: &str = "C:\\Program Files\\File Integrity Monitor\\config.yml";

// To parse files in yaml format
// Required dependencies
use yaml_rust::yaml::{Yaml, YamlLoader, Array};
// To use files IO operations.
use std::fs::{File, OpenOptions};
use std::io::Read;
use std::io::Write;
// To manage paths
use std::path::Path;
// To set log filter level
use simplelog::LevelFilter;
// To manage common functions
use crate::utils;
// Integrate FIM with external code
use crate::integration::Integration;
use std::sync::{Arc, Mutex};
use log::error;

// ----------------------------------------------------------------------------

#[derive(Clone)]
//#[derive(Clone)]
pub struct Config {
pub version: String,
pub path: String,
Expand All @@ -48,11 +45,11 @@ pub struct Config {
pub log_level: String,
pub log_max_file_size: usize,
pub system: String,
pub insecure: bool
pub insecure: bool,
pub events_lock: Arc<Mutex<bool>>,
pub log_lock: Arc<Mutex<bool>>
}

pub static mut TMP_EVENTS: bool = false;

impl Config {

pub fn clone(&self) -> Self {
Expand All @@ -76,7 +73,9 @@ impl Config {
log_level: self.log_level.clone(),
log_max_file_size: self.log_max_file_size,
system: self.system.clone(),
insecure: self.insecure
insecure: self.insecure,
events_lock: self.events_lock.clone(),
log_lock: self.log_lock.clone()
}
}

Expand Down Expand Up @@ -290,7 +289,9 @@ impl Config {
log_level,
log_max_file_size,
system: String::from(system),
insecure
insecure,
events_lock: Arc::new(Mutex::new(false)),
log_lock: Arc::new(Mutex::new(false)),
}
}

Expand Down Expand Up @@ -409,16 +410,43 @@ impl Config {

// ------------------------------------------------------------------------

pub fn get_events_file(&self) -> String {
unsafe {
if TMP_EVENTS {
format!("{}.tmp", self.events_file.clone())
}else{
self.events_file.clone()
pub fn get_lock_value(&self, lock: Arc<Mutex<bool>>) -> bool {
match Arc::into_inner(lock) {
None => {
error!("Could not retrieve events lock Arc value.");
false
},
Some(mutex) => match mutex.into_inner() {
Ok(guard) => guard,
Err(e) => {
error!("Could not retrieve events lock Mutex value, err: {}.", e);
false
}
}
}
}

// ------------------------------------------------------------------------

pub fn get_events_file(&self) -> String {
match self.get_lock_value(self.events_lock.clone()) {
false => self.events_file.clone(),
true => format!("{}.tmp", self.events_file.clone())
}
}

// ------------------------------------------------------------------------

pub fn get_mutex(&self, lock: Arc<Mutex<bool>>) -> Mutex<bool> {
match Arc::into_inner(lock.clone()) {
None => {
error!("Could not retrieve Mutex '{:?}'.", lock.clone());
Mutex::new(false)
},
Some(mutex) => mutex
}
}

}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -497,7 +525,9 @@ mod tests {
log_level: String::from(filter),
log_max_file_size: 64,
system: String::from("test"),
insecure: true
insecure: true,
events_lock: Arc::new(Mutex::new(false)),
log_lock: Arc::new(Mutex::new(false)),
}
}

Expand Down Expand Up @@ -1234,10 +1264,10 @@ mod tests {
Some(format!("test/unit/config/{}/monitor_integration.yml", os)
.as_str())
);
if os.clone() == "windows" {
if os == "windows" {
let integrations = config.get_integrations(2, config.monitor.clone());
assert_eq!(integrations.len(), 1);
}else if os.clone() == "macos"{
}else if os == "macos"{
let integrations = config.get_integrations(2, config.monitor.clone());
assert_eq!(integrations.len(), 1);
}else{
Expand Down
4 changes: 2 additions & 2 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ pub trait Event {
fn format_json(&self) -> String;
fn clone(&self) -> Self;
fn log(&self, file: String);
async fn send(&self);
async fn send(&self, cfg: config::Config);
//async fn route(&self);
async fn process(&self);
async fn process(&self, cfg: config::Config);
fn get_string(&self, field: String) -> String;
}

Expand Down
Loading

0 comments on commit 62898ed

Please sign in to comment.