#!/bin/bash set -euo pipefail # =============================================================================== # Linux System Audit Deployment Script # This script helps deploy and run the audit across multiple devices # Version: 2.0 - Enhanced with better error handling and security features # =============================================================================== # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INVENTORY_FILE="$SCRIPT_DIR/inventory.ini" PLAYBOOK_FILE="$SCRIPT_DIR/linux_audit_playbook.yml" AUDIT_SCRIPT="$SCRIPT_DIR/linux_system_audit.sh" RESULTS_DIR="$SCRIPT_DIR/audit_results" # Enhanced error handling error_handler() { local exit_code=$1 local line_no=$2 local last_command=$3 echo -e "${RED}Error occurred in: $last_command${NC}" echo -e "${RED}Exit code: $exit_code${NC}" echo -e "${RED}Line number: $line_no${NC}" exit $exit_code } # Set up error trap trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' print_status() { echo -e "${BLUE}[INFO]${NC} $1" } print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } print_error() { echo -e "${RED}[ERROR]${NC} $1" } check_dependencies() { print_status "Checking dependencies..." local missing_deps=() local optional_deps=() # Required dependencies if ! command -v ansible >/dev/null 2>&1; then missing_deps+=("ansible") fi if ! command -v ansible-playbook >/dev/null 2>&1; then missing_deps+=("ansible-playbook") fi # Optional but recommended dependencies if ! command -v jq >/dev/null 2>&1; then optional_deps+=("jq") fi if ! command -v tar >/dev/null 2>&1; then optional_deps+=("tar") fi if [ ${#missing_deps[@]} -ne 0 ]; then print_error "Missing required dependencies: ${missing_deps[*]}" echo "Please install Ansible:" echo " Ubuntu/Debian: sudo apt update && sudo apt install ansible" echo " Fedora: sudo dnf install ansible" echo " Or via pip: pip3 install ansible" exit 1 fi if [ ${#optional_deps[@]} -ne 0 ]; then print_warning "Missing optional dependencies: ${optional_deps[*]}" echo "These are recommended but not required:" echo " jq: For enhanced JSON processing" echo " tar: For result compression" fi print_success "All required dependencies found" # Check Ansible version local ansible_version=$(ansible --version | head -1 | awk '{print $2}') print_status "Ansible version: $ansible_version" } check_files() { print_status "Checking required files..." local missing_files=() if [ ! -f "$INVENTORY_FILE" ]; then missing_files+=("$INVENTORY_FILE") fi if [ ! -f "$PLAYBOOK_FILE" ]; then missing_files+=("$PLAYBOOK_FILE") fi if [ ! -f "$AUDIT_SCRIPT" ]; then missing_files+=("$AUDIT_SCRIPT") fi if [ ${#missing_files[@]} -ne 0 ]; then print_error "Missing files: ${missing_files[*]}" exit 1 fi print_success "All required files found" } test_connectivity() { print_status "Testing connectivity to hosts..." # Test connectivity with detailed output local connectivity_test=$(ansible all -i "$INVENTORY_FILE" -m ping --one-line 2>&1) local success_count=$(echo "$connectivity_test" | grep -c "SUCCESS" || echo "0") local total_hosts=$(ansible all -i "$INVENTORY_FILE" --list-hosts 2>/dev/null | grep -v "hosts" | wc -l) print_status "Connectivity test results: $success_count/$total_hosts hosts reachable" if [ "$success_count" -eq "$total_hosts" ]; then print_success "Successfully connected to all hosts" elif [ "$success_count" -gt 0 ]; then print_warning "Connected to $success_count/$total_hosts hosts" echo "Some hosts may not be reachable. Check your inventory file and SSH keys." echo "Failed connections:" echo "$connectivity_test" | grep -v "SUCCESS" || true read -p "Continue with available hosts? (y/N): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi else print_error "No hosts are reachable. Please check:" echo " 1. SSH key authentication is set up" echo " 2. Inventory file is correct" echo " 3. Hosts are online and accessible" echo " 4. Firewall rules allow SSH connections" exit 1 fi } run_audit() { print_status "Starting audit across all hosts..." # Create results directory mkdir -p "$RESULTS_DIR" # Run the playbook if ansible-playbook -i "$INVENTORY_FILE" "$PLAYBOOK_FILE" -v; then print_success "Audit completed successfully" else print_error "Audit failed. Check the output above for details." exit 1 fi } generate_summary_report() { print_status "Generating summary report..." local summary_file="$RESULTS_DIR/MASTER_SUMMARY_$(date +%Y%m%d_%H%M%S).txt" cat > "$summary_file" << EOF =============================================================================== COMPREHENSIVE LINUX SYSTEM AUDIT SUMMARY REPORT Generated: $(date) Script Version: 1.0 =============================================================================== OVERVIEW: --------- EOF # Count hosts local total_hosts=$(find "$RESULTS_DIR" -maxdepth 1 -type d | grep -v "^$RESULTS_DIR$" | wc -l) echo "Total hosts audited: $total_hosts" >> "$summary_file" echo "" >> "$summary_file" # Process each host for host_dir in "$RESULTS_DIR"/*; do if [ -d "$host_dir" ] && [ "$(basename "$host_dir")" != "audit_results" ]; then local hostname=$(basename "$host_dir") echo "=== $hostname ===" >> "$summary_file" if [ -f "$host_dir/SUMMARY.txt" ]; then cat "$host_dir/SUMMARY.txt" >> "$summary_file" else echo "No summary file found" >> "$summary_file" fi echo "" >> "$summary_file" fi done print_success "Summary report generated: $summary_file" } create_dashboard() { print_status "Creating dynamic HTML dashboard..." local dashboard_file="$RESULTS_DIR/dashboard.html" local all_results_file="$RESULTS_DIR/all_results.json" # Aggregate all JSON results into a single file echo "[" > "$all_results_file" first=true for host_dir in "$RESULTS_DIR"/*; do if [ -d "$host_dir" ]; then local json_file="$host_dir/results.json" if [ -f "$json_file" ]; then if [ "$first" = false ]; then echo "," >> "$all_results_file" fi cat "$json_file" >> "$all_results_file" first=false fi fi done echo "]" >> "$all_results_file" cat > "$dashboard_file" << 'EOF'