diff --git a/README.md b/README.md index e21e886..25b116a 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,56 @@ - **System Logging and Monitoring:** Ensures logging and monitoring systems are in place to detect unauthorized access or security breaches. - **File Integrity Monitoring:** Verifies that the server is monitoring critical files for changes. +### Running the Application + +To run the Kumo application, follow these steps: + +1. **Clone the repository:** + ```sh + git clone https://github.com/kintsdev/kumo.git + cd kumo + ``` + +2. **Build the application:** + ```sh + make build + ``` + +3. **Run the application:** + ```sh + sudo ./kumo + ``` + + Note: The application must be run as root to perform certain system checks. + +### Customizing Checks + +You can customize the system checks by modifying the `config.json` file. This file contains an array of checks, each with the following fields: + +- `Name`: The name of the check. +- `Cmd`: The command to be executed for the check. +- `ErrHint`: A hint message to be displayed if the check fails. + +Example `config.json` entry: +```json +{ + "Name": "Check Disk Space", + "Cmd": "df -h", + "ErrHint": "Ensure there is enough disk space available." +} +``` + +### Interpreting Results + +The results of the system checks are displayed in the terminal with the following format: + +- **Passed Checks:** Displayed with a green checkmark (✔) and the message "Passed". +- **Failed Checks:** Displayed with a red cross (✘) and the message "Failed" along with the error hint and the command output. + +Example output: +``` +✔ Check Disk Space Passed (df -h) +✘ Check Memory Usage Failed (Ensure there is enough free memory available. (free -m)) +``` + +Press 'q' to quit the application. diff --git a/config.json b/config.json new file mode 100644 index 0000000..d4eb810 --- /dev/null +++ b/config.json @@ -0,0 +1,77 @@ +[ + { + "Name": "Check Disk Space", + "Cmd": "df -h", + "ErrHint": "Ensure there is enough disk space available." + }, + { + "Name": "Check Memory Usage", + "Cmd": "free -m", + "ErrHint": "Ensure there is enough free memory available." + }, + { + "Name": "Check CPU Load", + "Cmd": "uptime", + "ErrHint": "Ensure the CPU load is within acceptable limits." + }, + { + "Name": "Check Running Processes", + "Cmd": "ps aux", + "ErrHint": "Ensure there are no unauthorized processes running." + }, + { + "Name": "Check Firewall Status", + "Cmd": "ufw status", + "ErrHint": "Ensure the firewall is active and configured correctly." + }, + { + "Name": "Check Open Ports", + "Cmd": "netstat -tuln", + "ErrHint": "Ensure only necessary ports are open." + }, + { + "Name": "Check User Accounts", + "Cmd": "cat /etc/passwd", + "ErrHint": "Ensure there are no unauthorized user accounts." + }, + { + "Name": "Check SSH Configuration", + "Cmd": "cat /etc/ssh/sshd_config", + "ErrHint": "Ensure SSH is configured securely." + }, + { + "Name": "Check Installed Packages", + "Cmd": "dpkg -l", + "ErrHint": "Ensure only necessary packages are installed." + }, + { + "Name": "Check System Logs", + "Cmd": "tail /var/log/syslog", + "ErrHint": "Review system logs for any unusual activity." + }, + { + "Name": "Check Network Configuration", + "Cmd": "ifconfig", + "ErrHint": "Ensure network interfaces are configured correctly." + }, + { + "Name": "Check System Uptime", + "Cmd": "uptime", + "ErrHint": "Ensure the system has been running without unexpected reboots." + }, + { + "Name": "Check Disk Usage", + "Cmd": "du -sh /", + "ErrHint": "Ensure disk usage is within acceptable limits." + }, + { + "Name": "Check Kernel Version", + "Cmd": "uname -r", + "ErrHint": "Ensure the system is running a supported kernel version." + }, + { + "Name": "Check System Updates", + "Cmd": "apt-get update", + "ErrHint": "Ensure the system has the latest updates installed." + } +] diff --git a/main.go b/main.go index 55a23bd..ac7a4d5 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "io/ioutil" "os" "os/exec" "strings" @@ -28,6 +29,12 @@ type CheckResult struct { Message string `json:"message"` } +type Check struct { + Name string `json:"name"` + Cmd string `json:"cmd"` + ErrHint string `json:"errHint"` +} + type model struct { results []CheckResult quitting bool @@ -49,29 +56,14 @@ var ( // Spinner animation frames var spinnerFrames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"} -func runChecks() []CheckResult { +func runChecks(configFile string) []CheckResult { var wg sync.WaitGroup results := make([]CheckResult, 0) mutex := &sync.Mutex{} - checks := []struct { - Name string - Cmd string - ErrHint string - }{ - {"System Update", "sudo apt update -y 2>/dev/null ", "Failed to fetch updates. Ensure apt is installed and configured."}, - {"System Updateable", "sudo apt list --upgradable 2>/dev/null", "Failed to check for upgradable packages."}, - {"Kernel Check", "uname -r", "Kernel information not available."}, - {"UFW Firewall Status", "sudo ufw status | grep -q active", "UFW firewall is inactive or not installed."}, - {"SSH Security", "grep -q 'PermitRootLogin no' /etc/ssh/sshd_config", "Root login over SSH is permitted. Update sshd_config."}, - {"Disk Usage", "df -h > /dev/null", "Disk usage information could not be retrieved."}, - {"Memory Usage", "free -m", "Memory usage data is unavailable."}, - {"Service Status (rsyslog)", "systemctl is-active --quiet rsyslog", "rsyslog service is not active."}, - {"Cron Jobs", "crontab -l", "No cron jobs found for the current user."}, - {"TLS Support", "openssl ciphers -v | grep -q 'TLSv1.2\\|TLSv1.3'", "TLSv1.2 or TLSv1.3 support is missing."}, - {"Password Policy", "grep -q 'minlen' /etc/security/pwquality.conf", "Password policy not enforced. Check pwquality.conf."}, - {"Disk Encryption", "lsblk -o NAME,TYPE,SIZE,MOUNTPOINT,UUID,ENCRYPTION | grep -i crypt", "Disk encryption not enabled."}, - {"Unnecessary Services", "systemctl list-units --type=service --state=running | grep -i 'unwanted-service'", "Unnecessary services are running."}, + checks, err := loadChecks(configFile) + if err != nil { + log.Fatalf("Error loading checks: %v", err) } for _, check := range checks { @@ -81,7 +73,7 @@ func runChecks() []CheckResult { start := time.Now() status, msg := runCommand(cmd) if status == "Failed" { - msg = errHint + " (" + msg + ")" + msg = fmt.Sprintf("%s (Command: %s, Error: %s)", errHint, cmd, msg) } elapsed := time.Since(start) @@ -102,18 +94,33 @@ func runChecks() []CheckResult { func runCommand(cmd string) (string, string) { out, err := exec.Command("bash", "-c", cmd).CombinedOutput() if err != nil { - return "Failed", strings.TrimSpace(string(out)) + return "Failed", fmt.Sprintf("Command: %s, Output: %s, Error: %v", cmd, strings.TrimSpace(string(out)), err) } return "Passed", strings.TrimSpace(string(out)) } +func loadChecks(configFile string) ([]Check, error) { + file, err := ioutil.ReadFile(configFile) + if err != nil { + return nil, err + } + + var checks []Check + err = json.Unmarshal(file, &checks) + if err != nil { + return nil, err + } + + return checks, nil +} + type checkResultsMsg []CheckResult type quitMsg struct{} func (m model) Init() tea.Cmd { return func() tea.Msg { - return checkResultsMsg(runChecks()) + return checkResultsMsg(runChecks("config.json")) } }