1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! # Security Module
//!
//! This module provides functions for implementing various security measures on a Linux server.
//! It includes functionality for configuring Fail2Ban, setting up advanced security measures
//! (SELinux or AppArmor), implementing rootkit detection, and scheduling regular security scans.

use crate::config::Config;
use crate::distro::{get_package_manager, PackageManager};
use crate::rollback::RollbackManager;
use crate::utils::run_command;
use log::info;
use std::error::Error;

/// Implements all security measures based on the provided configuration.
///
/// This function orchestrates the implementation of various security measures including:
/// - Configuring Fail2Ban
/// - Setting up advanced security (SELinux or AppArmor)
/// - Setting up rootkit detection
/// - Configuring regular security scans
///
/// # Arguments
///
/// * `config` - A reference to the `Config` struct containing user-defined configuration options
/// * `rollback` - A reference to the `RollbackManager` for managing system state
///
/// # Errors
///
/// Returns an error if any of the security measures fail to implement
pub fn implement_security_measures(
    config: &Config,
    rollback: &RollbackManager,
) -> Result<(), Box<dyn Error>> {
    info!("Implementing security measures...");

    let snapshot = rollback.create_snapshot()?;

    configure_fail2ban()?;
    setup_advanced_security(config)?;
    setup_rootkit_detection(config)?;
    setup_security_scans()?;

    rollback.commit_snapshot(snapshot)?;

    info!("Security measures implemented");
    Ok(())
}

/// Configures and starts the Fail2Ban service.
///
/// This function installs Fail2Ban, creates a basic configuration for SSH,
/// and starts the Fail2Ban service.
///
/// # Errors
///
/// Returns an error if Fail2Ban installation or configuration fails
pub fn configure_fail2ban() -> Result<(), Box<dyn Error>> {
    let package_manager = get_package_manager()?;
    match package_manager {
        PackageManager::Apt => run_command("apt", &["install", "-y", "fail2ban"])?,
        PackageManager::Yum => run_command("yum", &["install", "-y", "fail2ban"])?,
        PackageManager::Dnf => run_command("dnf", &["install", "-y", "fail2ban"])?,
    }

    let fail2ban_config = r#"
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
"#;
    std::fs::write("/etc/fail2ban/jail.local", fail2ban_config)?;

    run_command("systemctl", &["enable", "fail2ban"])?;
    run_command("systemctl", &["start", "fail2ban"])?;

    Ok(())
}

/// Sets up advanced security measures based on the Linux distribution.
///
/// For Ubuntu, this function sets up AppArmor.
/// For CentOS or Fedora, this function sets up SELinux.
///
/// # Arguments
///
/// * `config` - A reference to the `Config` struct containing user-defined configuration options
///
/// # Errors
///
/// Returns an error if the setup fails or if the Linux distribution is not supported
pub fn setup_advanced_security(config: &Config) -> Result<(), Box<dyn Error>> {
    if config.security_level == "advanced" {
        // Enable and configure SELinux or AppArmor based on the distribution
        match config.linux_distro.as_str() {
            "ubuntu" => {
                run_command("apt", &["install", "-y", "apparmor", "apparmor-utils"])?;
                run_command("aa-enforce", &["/etc/apparmor.d/*"])?;
            }
            "centos" | "fedora" => {
                run_command(
                    "yum",
                    &["install", "-y", "selinux-policy", "selinux-policy-targeted"],
                )?;
                std::fs::write(
                    "/etc/selinux/config",
                    "SELINUX=enforcing\nSELINUXTYPE=targeted\n",
                )?;
            }
            _ => return Err("Unsupported Linux distribution for advanced security".into()),
        }
    }
    Ok(())
}

/// Sets up rootkit detection tools (rkhunter and chkrootkit).
///
/// This function installs rkhunter and chkrootkit, then updates the rkhunter database.
///
/// # Arguments
///
/// * `config` - A reference to the `Config` struct (unused in the current implementation)
///
/// # Errors
///
/// Returns an error if installation or configuration of rootkit detection tools fails
pub fn setup_rootkit_detection(config: &Config) -> Result<(), Box<dyn Error>> {
    let package_manager = get_package_manager()?;
    match package_manager {
        PackageManager::Apt => run_command("apt", &["install", "-y", "rkhunter", "chkrootkit"])?,
        PackageManager::Yum => run_command("yum", &["install", "-y", "rkhunter", "chkrootkit"])?,
        PackageManager::Dnf => run_command("dnf", &["install", "-y", "rkhunter", "chkrootkit"])?,
    }

    // Update rkhunter database
    run_command("rkhunter", &["--update"])?;
    run_command("rkhunter", &["--propupd"])?;

    Ok(())
}

/// Sets up regular security scans using rkhunter and chkrootkit.
///
/// This function creates a script to run both rkhunter and chkrootkit,
/// then sets up a weekly cron job to execute this script.
///
/// # Errors
///
/// Returns an error if creating the script or setting up the cron job fails
pub fn setup_security_scans() -> Result<(), Box<dyn Error>> {
    let scan_script = r#"#!/bin/bash
rkhunter --check --skip-keypress
chkrootkit
"#;
    std::fs::write("/usr/local/bin/security_scan.sh", scan_script)?;
    run_command("chmod", &["+x", "/usr/local/bin/security_scan.sh"])?;

    // Add weekly cron job for security scans
    let cron_job =
        "0 2 * * 0 root /usr/local/bin/security_scan.sh > /var/log/security_scan.log 2>&1\n";
    std::fs::write("/etc/cron.d/security_scan", cron_job)?;

    Ok(())
}