Skip to content

Commit

Permalink
Merge branch 'main' of github.com:Achiefs/fim into 149-fix-cpu-load
Browse files Browse the repository at this point in the history
  • Loading branch information
okynos committed Apr 19, 2024
2 parents 0468cd8 + 49db90c commit 7bcbdb3
Show file tree
Hide file tree
Showing 15 changed files with 145 additions and 50 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fim"
version = "0.4.11"
version = "0.5.0"
authors = ["José Fernández <´[email protected]´>"]
edition = "2021"

Expand Down
1 change: 1 addition & 0 deletions pkg/deb/builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pkg_dir="${sources_dir}/pkg/deb"

mkdir -p ${sources_dir}
cp -R ${base_dir}/* ${sources_dir}/
sed -i "s|FIM_VERSION|${version}|g" ${sources_dir}/pkg/fim.1

# Generating directory structure to build the .deb package
cd ${build_dir} && tar -czf ${pkg_name}.orig.tar.gz "${pkg_name}"
Expand Down
6 changes: 6 additions & 0 deletions pkg/deb/debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
fim (0.5.0-1) xenial; urgency=medium

* More info: https://github.com/Achiefs/fim/releases/tag/v0.5.0

-- Jose Fernandez <[email protected]> Fri, 19 Apr 2024 16:04:00 +0000

fim (0.4.11-1) xenial; urgency=medium

* More info: https://github.com/Achiefs/fim/releases/tag/v0.4.11
Expand Down
4 changes: 2 additions & 2 deletions pkg/fim.1
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
.\" *
.\" **************************************************************************
.\"
.TH fim 1 "01 Jun 2022" "FIM 0.4.11" "FIM Manual"
.TH fim 1 "01 Jun 2022" "FIM FIM_VERSION" "FIM Manual"

.SH NAME
.B FIM
Expand Down Expand Up @@ -62,7 +62,7 @@ The events are stored in /var/lib/fim/events.json
.SH COPYRIGHT
.PP
Copyright 2021 Achiefs. All rights reserved
https://achiefs.github.io/fim/
https://achiefs.com/

.SH CREDITS
.PP
Expand Down
2 changes: 2 additions & 0 deletions pkg/msi/builder.ps1
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
$version = (gc ..\..\Cargo.toml | findstr "version" | select -First 1).split(" ")[2].trim("`"", " ")

(Get-Content .\fim.wxs) -replace 'FIM_VERSION', $version | Set-Content -NoNewLine fim.wxs

cd ..\..\
cargo build --release
cd pkg\msi
Expand Down
2 changes: 1 addition & 1 deletion pkg/msi/fim.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
<Product Name='File Integrity Monitor' Manufacturer='Achiefs LLC.' Id='*'
UpgradeCode='5b9136b1-f19d-4af0-9efe-356fabdf1467'
Language='1033' Codepage='1252' Version='0.4.11'>
Language='1033' Codepage='1252' Version='FIM_VERSION'>
<Package Id='*' Keywords='Installer'
Description="FIM is a Host-based file monitoring tool that performs file system analysis and real time alerting."
Comments='FIM is an open source application, coded in Rust.'
Expand Down
1 change: 1 addition & 0 deletions pkg/rpm/builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mkdir -p ${rpm_build_dir}/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
# Prepare the sources directory to build the source tar.gz
mkdir -p ${sources_dir}
cp -R ../../* ${sources_dir}
sed -i "s|FIM_VERSION|${version}|g" ${sources_dir}/pkg/fim.1

cp ${brand}.spec ${rpm_build_dir}/SPECS/${pkg_name}.spec

Expand Down
3 changes: 3 additions & 0 deletions pkg/rpm/fim.spec
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ rm -fr %{buildroot}
# -----------------------------------------------------------------------------

%changelog
* Fri Apr 19 2024 support <[email protected]> - 0.5.0
- More info: https://github.com/Achiefs/fim/releases/tag/v0.5.0

* Fri Apr 19 2024 support <[email protected]> - 0.4.11
- More info: https://github.com/Achiefs/fim/releases/tag/v0.4.11

Expand Down
14 changes: 4 additions & 10 deletions src/auditevent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,6 @@ impl Event {
pub fn log(&self, file: &str){
let mut events_file = OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(file)
.expect("(auditevent::log) Unable to open events log file.");
Expand Down Expand Up @@ -631,17 +630,14 @@ mod tests {
(String::from("name"), String::from("/tmp"))
]);*/

let mut test_file = fs::File::create("/etc/auditevent_test_from.txt").unwrap();
test_file.write_all(b"Hello, world!").unwrap();

let paths = Vec::from([
HashMap::<String, String>::from([
(String::from("name"), String::from("/etc")),
(String::from("nametype"), String::from("PARENT"))
]),
HashMap::<String, String>::from([
(String::from("nametype"), String::from("nametype")),
(String::from("name"), String::from("/etc/auditevent_test_from.txt")),
(String::from("name"), String::from("/tmp/test.txt")),
(String::from("ogid"), String::from("ogid")),
(String::from("rdev"), String::from("rdev")),
(String::from("cap_fver"), String::from("cap_fver")),
Expand Down Expand Up @@ -685,9 +681,9 @@ mod tests {
assert_eq!(utils::get_hostname(), event.hostname);
assert_eq!(String::from("FIM"), event.node);
assert_eq!(String::from(config::VERSION), event.version);
assert_eq!(String::from("/etc"), event.path);
assert_eq!(String::from("auditevent_test_from.txt"), event.file);
assert_eq!(13, event.size);
assert_eq!(String::from("/tmp"), event.path);
assert_eq!(String::from("test.txt"), event.file);
assert_eq!(0, event.size);
//assert_eq!(..., event.labels);
//assert_eq!(..., event.parent);
assert_eq!(String::from("nametype"), event.operation);
Expand Down Expand Up @@ -742,8 +738,6 @@ mod tests {
let event = Event::from(syscall, cwd, proctitle, paths.clone(), config.clone());
assert_eq!(String::from("bash"), event.proctitle);

remove_test_file("/tmp/auditevent_test_from.txt");

}
}

Expand Down
10 changes: 3 additions & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (C) 2021, Achiefs.

// Global constants definitions
pub const VERSION: &str = "0.4.11";
pub const VERSION: &str = "0.5.0";
pub const NETWORK_MODE: &str = "NETWORK";
pub const FILE_MODE: &str = "FILE";
pub const BOTH_MODE: &str = "BOTH";
Expand Down Expand Up @@ -300,7 +300,6 @@ impl Config {
pub fn get_level_filter(&self) -> LevelFilter {
let mut log = OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(self.log_file.clone())
.expect("(get_level_filter) Unable to open events log file.");
Expand Down Expand Up @@ -378,16 +377,13 @@ impl Config {
// Returns if a given path and filename is in the configuration paths
pub fn path_in(&self, raw_path: &str, cwd: &str, vector: Vec<Yaml>) -> bool {
// Iterate over monitoring paths to match ignore string and ignore event or not
match vector.iter().any(|it| {
vector.iter().any(|it| {
if raw_path.starts_with("./") || raw_path == "." || !raw_path.contains('/') {
utils::match_path(cwd, it["path"].as_str().unwrap())
}else{
utils::match_path(raw_path, it["path"].as_str().unwrap())
}
}){
true => true,
false => false
}
})
}

// ------------------------------------------------------------------------
Expand Down
1 change: 0 additions & 1 deletion src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ impl Event {
pub fn log(&self, file: String){
let mut events_file = OpenOptions::new()
.create(true)
.write(true)
.append(true)
.open(file)
.expect("(log) Unable to open events log file.");
Expand Down
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ fn init(){
GCONFIG.clone().unwrap().get_level_filter(),
Config::default(),
fs::OpenOptions::new()
.write(true)
.create(true)
.append(true)
.open(GCONFIG.clone().unwrap().log_file)
Expand Down
37 changes: 15 additions & 22 deletions src/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ use std::time::{SystemTime, UNIX_EPOCH};
use time::OffsetDateTime;
// To use intersperse()
use itertools::Itertools;
// To run commands
use std::process::Command;
// Event handling
use notify::event::{EventKind, AccessKind};

Expand Down Expand Up @@ -69,6 +67,17 @@ async fn push_template(destination: &str){

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

fn clean_audit_rules(config: &config::Config){
for element in config.audit.clone() {
let path = element["path"].as_str().unwrap();
let rule = utils::get_audit_rule_permissions(element["rule"].as_str());
utils::run_auditctl(&["-W", path, "-k", "fim", "-p", &rule]);
}
std::process::exit(0);
}

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

// Function that monitorize files in loop
pub async fn monitor(tx: mpsc::Sender<Result<notify::Event, notify::Error>>,
rx: mpsc::Receiver<Result<notify::Event, notify::Error>>){
Expand Down Expand Up @@ -116,12 +125,8 @@ pub async fn monitor(tx: mpsc::Sender<Result<notify::Event, notify::Error>>,
if ! config.audit.is_empty() && utils::get_os() == "linux" && utils::check_auditd() {
for element in config.audit.clone() {
let path = element["path"].as_str().unwrap();
match Command::new("/usr/sbin/auditctl")
.args(["-w", path, "-k", "fim", "-p", "wax"])
.output() {
Ok(d) => debug!("Auditctl command info: {:?}", d),
Err(e) => error!("Auditctl command error: {}", e)
};
let rule = utils::get_audit_rule_permissions(element["rule"].as_str());
utils::run_auditctl(&["-w", path, "-k", "fim", "-p", &rule]);
info!("Checking audit path: {}", path);

match element["allowed"].as_vec() {
Expand All @@ -148,20 +153,8 @@ pub async fn monitor(tx: mpsc::Sender<Result<notify::Event, notify::Error>>,

// Remove auditd rules introduced by FIM
// Setting ctrl + C handler
let copied_config = config.clone();
match ctrlc::set_handler(move || {
for element in &copied_config.audit {
let path = element["path"].as_str().unwrap();
match Command::new("/usr/sbin/auditctl")
.args(["-W", path, "-k", "fim", "-p", "wax"])
.output()
{
Ok(d) => debug!("Auditctl command info: {:?}", d),
Err(e) => error!("Auditctl command error: {}", e)
};
}
std::process::exit(0);
}) {
let cloned_config = config.clone();
match ctrlc::set_handler(move || clean_audit_rules(&cloned_config)) {
Ok(_v) => debug!("Handler Ctrl-C set and listening"),
Err(e) => error!("Error setting Ctrl-C handler, the process will continue without signal handling, Error: '{}'", e)
}
Expand Down
83 changes: 78 additions & 5 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::path::{Path, PathBuf};
// To run commands
use std::process::Command;
// To log the program process
use log::{warn, debug};
use log::{warn, debug, error};
// To manage maps
use std::collections::HashMap;

Expand Down Expand Up @@ -76,7 +76,15 @@ pub fn get_machine_id() -> String {

// Function to get file name of a given path
pub fn get_filename_path(path: &str) -> String {
String::from(Path::new(path).file_name().unwrap().to_str().unwrap())
String::from(
match Path::new(path).file_name() {
Some(value) => value,
None => {
debug!("Cannot retrieve event file, event path is empty.");
std::ffi::OsStr::new(path)
}
}.to_str().unwrap()
)
}

// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -230,6 +238,39 @@ pub fn get_file_size(filename: &str) -> u64 {

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

pub fn get_audit_rule_permissions(value: Option<&str>) -> String {
let mut rule: String = String::new();
match value {
Some(value) => {
for c in value.chars(){
match c {
'r'|'R' => rule.push('r'),
'w'|'W' => rule.push('w'),
'a'|'A' => rule.push('a'),
'x'|'X' => rule.push('x'),
_ => rule = String::from("wax")
}
}
rule.clone()
},
None => String::from("wax")
}
}

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

pub fn run_auditctl(args: &[&str]) {
match Command::new("/usr/sbin/auditctl")
.args(args)
.output()
{
Ok(d) => debug!("Auditctl command info: {:?}", d),
Err(e) => error!("Auditctl command error: {}", e)
};
}

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

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -315,9 +356,8 @@ mod tests {
// ------------------------------------------------------------------------

#[test]
#[should_panic]
fn test_get_filename_path_panic() {
get_filename_path("/");
fn test_get_filename_path_empty() {
assert_eq!(get_filename_path("/"), "/");
}

// ------------------------------------------------------------------------
Expand Down Expand Up @@ -385,4 +425,37 @@ mod tests {
}
}

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

#[cfg(target_os = "linux")]
#[test]
fn test_get_audit_rule_permissions() {
use crate::config::Config;
let config = Config::new(&get_os(), Some("test/unit/config/linux/audit_rule.yml"));
assert_eq!(get_audit_rule_permissions(config.audit[0]["rule"].as_str()), "rwax");
}

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

#[cfg(target_os = "linux")]
#[test]
fn test_run_auditctl() {
use crate::config::Config;
let config = Config::new(&get_os(), Some("test/unit/config/linux/audit_rule.yml"));
let path = config.audit[0]["path"].as_str().unwrap();
let rule = config.audit[0]["rule"].as_str().unwrap();
run_auditctl(&["-w", path, "-k", "fim", "-p", rule]);

match Command::new("/usr/sbin/auditctl")
.args(["-l", "-k", "fim"])
.output()
{
Ok(data) => assert_eq!(String::from_utf8(data.stdout).unwrap(), "-w /tmp -p rwxa -k fim\n"),
Err(e) => {
println!("{:?}", e);
assert!(true)
}
};
}

}
28 changes: 28 additions & 0 deletions test/unit/config/linux/audit_rule.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
node: "FIM"

# Events configuration, where to store produced events
events:
destination: file
file: /var/lib/fim/events.json

# Audit extended files and folders information
audit:
- path: /tmp
labels: ["tmp", "linux"]
ignore: [".swp"]
allowed: [".txt", ".rs"]
rule: "rwax"

# Simple files and folders information
monitor:
- path: /bin/
- path: /usr/bin/
labels: ["usr/bin", "linux"]
- path: /etc
labels: ["etc", "linux"]

# App procedure and errors logging
log:
file: /var/log/fim/fim.log
# Available levels [debug, info, error, warning]
level: info

0 comments on commit 7bcbdb3

Please sign in to comment.