use tracing::error;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Instant;
#[derive(Debug, Clone, PartialEq)]
pub enum ConfigStatus {
NotApplied,
Pending,
Applied,
Failed,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SecurityLevel {
Basic,
Enhanced,
Strict,
Custom,
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct HardeningConfig {
name: String,
status: ConfigStatus,
level: SecurityLevel,
settings: HashMap<String, String>,
last_modified: Instant,
auto_save_enabled: bool,
}
pub struct SystemHardening {
configs: Arc<Mutex<HashMap<String, HardeningConfig>>>,
input_counter: Arc<Mutex<usize>>,
auto_save_frequency: usize,
}
impl SystemHardening {
pub fn new(auto_save_frequency: usize) -> Self {
Self {
configs: Arc::new(Mutex::new(HashMap::new())),
input_counter: Arc::new(Mutex::new(0)),
auto_save_frequency,
}
}
pub fn configure_component(
&self,
name: &str,
level: SecurityLevel,
settings: HashMap<String, String>,
auto_save: bool,
) -> Result<(), String> {
{
let mut configs = self
.configs
.lock()
.map_err(|e| format!("Mutex lock error: {e}"))?;
let config = HardeningConfig {
name: name.to_string(),
status: ConfigStatus::NotApplied,
level,
settings,
last_modified: Instant::now(),
auto_save_enabled: auto_save,
};
configs.insert(name.to_string(), config);
}
let _ = self.record_input_and_check_save();
Ok(())
}
fn record_input_and_check_save(&self) -> Result<(), String> {
let mut counter = self
.input_counter
.lock()
.map_err(|e| format!("Mutex lock error: {e}"))?;
*counter += 1;
if *counter % self.auto_save_frequency == 0 {
match self.save_state_to_memory() {
Ok(_) => println!(
"Auto-saved security configuration after {} changes",
*counter
),
Err(e) => eprintln!("Failed to auto-save security configuration: {e}"),
}
}
Ok(())
}
fn save_state_to_memory(&self) -> Result<(), String> {
let configs = self
.configs
.lock()
.map_err(|e| format!("Mutex lock error: {e}"))?;
println!(
"In-memory security configuration snapshot created: {} components",
configs.len()
);
Ok(())
}
pub fn apply_hardening(&self, component_name: &str) -> Result<ConfigStatus, String> {
let status = {
let mut configs = self
.configs
.lock()
.map_err(|e| format!("Mutex lock error: {e}"))?;
let config = match configs.get_mut(component_name) {
Some(config) => config,
None => {
return Err(format!(
"No configuration found for component {component_name}"
))
}
};
println!(
"Applying security configuration for {}: {:?}",
component_name, config.level
);
config.status = ConfigStatus::Applied;
config.last_modified = Instant::now();
config.status.clone()
};
let _ = self.record_input_and_check_save();
Ok(status)
}
pub fn set_security_setting(
&self,
component_name: &str,
key: &str,
value: &str,
) -> Result<(), String> {
{
let mut configs = self
.configs
.lock()
.map_err(|e| format!("Mutex lock error: {e}"))?;
let config = match configs.get_mut(component_name) {
Some(config) => config,
None => {
return Err(format!(
"No configuration found for component {component_name}"
))
}
};
config.settings.insert(key.to_string(), value.to_string());
config.status = ConfigStatus::Pending; config.last_modified = Instant::now();
}
let _ = self.record_input_and_check_save();
Ok(())
}
pub fn get_component_config(&self, component_name: &str) -> Option<HardeningConfig> {
match self.configs.lock() {
Ok(configs) => configs.get(component_name).cloned(),
Err(e) => {
error!("Mutex lock error: {}", e);
None
}
}
}
pub fn get_all_configs(&self) -> Vec<HardeningConfig> {
match self.configs.lock() {
Ok(configs) => configs.values().cloned().collect(),
Err(e) => {
error!("Mutex lock error: {}", e);
Vec::new()
}
}
}
pub fn get_stats(&self) -> (usize, usize) {
let counter = match self.input_counter.lock() {
Ok(counter) => *counter,
Err(e) => {
error!("Mutex lock error: {}", e);
0
}
};
let config_count = match self.configs.lock() {
Ok(configs) => configs.len(),
Err(e) => {
error!("Mutex lock error: {}", e);
0
}
};
(counter, config_count)
}
pub fn apply_all_pending(&self) -> Vec<(String, Result<ConfigStatus, String>)> {
let pending_components = match self.configs.lock() {
Ok(configs) => {
let components: Vec<String> = configs
.iter()
.filter(|(_, config)| config.status == ConfigStatus::Pending)
.map(|(name, _)| name.clone())
.collect();
drop(configs); components
}
Err(e) => {
let error_msg = format!("Mutex lock error: {e}");
return vec![("general".to_string(), Err(error_msg))];
}
};
let mut results = Vec::new();
for component_name in pending_components {
results.push((
component_name.clone(),
self.apply_hardening(&component_name),
));
}
results
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_configuration_and_auto_save() -> Result<(), Box<dyn std::error::Error>> {
let hardening = SystemHardening::new(20);
for i in 0..25 {
let mut settings = HashMap::new();
settings.insert("firewall".to_string(), "enabled".to_string());
settings.insert("port_scanning".to_string(), "block".to_string());
hardening.configure_component(
&format!("component_{i}"),
SecurityLevel::Enhanced,
settings,
true,
)?;
}
let (changes, configs) = hardening.get_stats();
assert_eq!(changes, 25);
assert_eq!(configs, 25);
Ok(())
}
#[test]
fn test_apply_hardening() -> Result<(), Box<dyn std::error::Error>> {
let hardening = SystemHardening::new(10);
let mut settings = HashMap::new();
settings.insert("firewall".to_string(), "enabled".to_string());
hardening.configure_component("network", SecurityLevel::Strict, settings, true)?;
let result = hardening.apply_hardening("network")?;
assert_eq!(result, ConfigStatus::Applied);
if let Some(config) = hardening.get_component_config("network") {
assert_eq!(config.status, ConfigStatus::Applied);
} else {
return Err("Component config not found".into());
}
Ok(())
}
}