Tutorial

New updates and improvements to Roundfleet.

Network Monitoring on macOS

Monitor and control network activity across your Roundfleet devices using advanced network monitoring techniques, bandwidth analysis, and enterprise security controls. This tutorial provides comprehensive tools for implementing organizational network management and security policies.

Understanding macOS Network Monitoring

macOS provides several tools for network activity monitoring:

  • lsof - List open files and network connections
  • netstat - Display network connections and routing tables
  • nettop - Real-time network usage by process
  • tcpdump - Packet capture and analysis
  • Little Snitch - Application-level firewall and network monitor

Basic Network Connection Monitoring

List Internet-Connected Apps

#!/bin/bash

# List unique processes with internet connections
lsof -nPi | cut -f 1 -d " " | uniq | tail -n +2

echo "Internet-connected processes listed"

Detailed Network Connections

#!/bin/bash

# Show detailed network connection information
echo "=== Active Network Connections ==="
lsof -nPi

echo -e "\n=== Network Statistics ==="
netstat -an | head -20

Process-Specific Network Activity

#!/bin/bash

# Monitor specific application network activity
APP_NAME="Chrome"

echo "Network connections for $APP_NAME:"
lsof -nPi | grep -i "$APP_NAME"

Enterprise Network Monitoring System

#!/bin/bash

# Roundfleet Enterprise Network Monitoring System
# Comprehensive network activity monitoring and security management

# Configuration
ROUNDFLEET_DIR="/etc/roundfleet"
MONITORING_DIR="$ROUNDFLEET_DIR/network_monitoring"
REPORTS_DIR="$ROUNDFLEET_DIR/reports"
COMPLIANCE_DIR="$ROUNDFLEET_DIR/compliance"
AUDIT_DIR="$ROUNDFLEET_DIR/audit"
LOG_FILE="/var/log/roundfleet_network_monitoring.log"
ALERTS_DIR="$ROUNDFLEET_DIR/alerts"

# Create directory structure
create_directories() {
    local dirs=("$ROUNDFLEET_DIR" "$MONITORING_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$ALERTS_DIR")
    for dir in "${dirs[@]}"; do
        [[ ! -d "$dir" ]] && mkdir -p "$dir"
    done
}

# Logging function
log_action() {
    local message="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] $message" | tee -a "$LOG_FILE"
}

# Application Categories for Network Monitoring
declare -A APP_CATEGORIES=(
    ["business_apps"]="Slack,Zoom,Microsoft Teams,Office 365,Salesforce"
    ["development_tools"]="Xcode,Visual Studio Code,Docker,Git,npm"
    ["browsers"]="Chrome,Firefox,Safari,Edge"
    ["communication"]="Mail,Messages,FaceTime,Skype"
    ["cloud_storage"]="Dropbox,Google Drive,OneDrive,iCloud"
    ["entertainment"]="Spotify,Netflix,YouTube,Steam"
    ["security_tools"]="1Password,Little Snitch,Wireshark"
    ["system_services"]="locationd,cloudd,nsurlsessiond,trustd"
)

# Network Monitoring Policies
declare -A MONITORING_POLICIES=(
    ["strict_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:monitored,communication:allowed,cloud_storage:monitored,entertainment:blocked,security_tools:allowed,system_services:allowed"
    ["balanced_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:monitored,security_tools:allowed,system_services:allowed"
    ["minimal_monitoring"]="business_apps:allowed,development_tools:allowed,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:allowed,security_tools:allowed,system_services:allowed"
    ["development_focused"]="business_apps:allowed,development_tools:priority,browsers:allowed,communication:allowed,cloud_storage:allowed,entertainment:blocked,security_tools:allowed,system_services:allowed"
    ["security_lockdown"]="business_apps:monitored,development_tools:monitored,browsers:monitored,communication:monitored,cloud_storage:blocked,entertainment:blocked,security_tools:allowed,system_services:allowed"
)

# Bandwidth Thresholds (in MB/s)
declare -A BANDWIDTH_THRESHOLDS=(
    ["critical"]=100
    ["high"]=50
    ["moderate"]=20
    ["low"]=5
)

# Get comprehensive network activity
get_network_activity() {
    local monitoring_level="$1"
    local output_file="$MONITORING_DIR/network_activity_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting network activity monitoring: $monitoring_level"
    
    # Get basic network connections
    local connections=$(lsof -nPi 2>/dev/null | tail -n +2)
    local unique_processes=$(echo "$connections" | cut -f 1 -d " " | sort | uniq)
    
    # Get detailed process information
    local detailed_info=""
    while IFS= read -r process; do
        [[ -z "$process" ]] && continue
        
        local pids=$(pgrep -f "$process" 2>/dev/null | head -5)
        for pid in $pids; do
            local cpu_usage=$(ps -p "$pid" -o %cpu= 2>/dev/null | tr -d ' ')
            local mem_usage=$(ps -p "$pid" -o %mem= 2>/dev/null | tr -d ' ')
            local process_connections=$(echo "$connections" | grep "^$process" | wc -l)
            
            if [[ -n "$cpu_usage" && -n "$mem_usage" ]]; then
                detailed_info="$detailed_info{\"process\":\"$process\",\"pid\":$pid,\"cpu\":$cpu_usage,\"memory\":$mem_usage,\"connections\":$process_connections},"
            fi
        done
    done <<< "$unique_processes"
    
    # Remove trailing comma and format JSON
    detailed_info="${detailed_info%,}"
    
    cat > "$output_file" << EOF
{
  "monitoring_metadata": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "monitoring_level": "$monitoring_level",
    "report_version": "1.0"
  },
  "network_activity": {
    "total_processes": $(echo "$unique_processes" | wc -l),
    "active_connections": $(echo "$connections" | wc -l),
    "processes": [$detailed_info]
  },
  "system_metrics": {
    "load_average": "$(uptime | awk -F'load average:' '{print $2}' | tr -d ' ')",
    "memory_pressure": "$(memory_pressure 2>/dev/null || echo 'unknown')",
    "network_interfaces": $(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
  }
}
EOF
    
    log_action "Network activity report saved: $output_file"
    echo "$output_file"
}

# Analyze bandwidth usage
analyze_bandwidth_usage() {
    local monitoring_duration="$1"
    local analysis_file="$MONITORING_DIR/bandwidth_analysis_$(date +%Y%m%d_%H%M%S).txt"
    
    log_action "Starting bandwidth analysis for $monitoring_duration seconds"
    
    # Use nettop for bandwidth monitoring
    timeout "$monitoring_duration" nettop -P -t wifi -t ethernet -l 1 > "$analysis_file" 2>/dev/null &
    local nettop_pid=$!
    
    sleep "$monitoring_duration"
    
    # Kill nettop if still running
    kill "$nettop_pid" 2>/dev/null
    
    # Parse bandwidth data
    local high_bandwidth_processes=""
    if [[ -f "$analysis_file" ]]; then
        # Extract processes with high bandwidth usage
        while IFS= read -r line; do
            [[ "$line" =~ ^[[:space:]]*[0-9] ]] || continue
            
            local process_name=$(echo "$line" | awk '{print $2}')
            local bytes_in=$(echo "$line" | awk '{print $3}' | sed 's/[^0-9]//g')
            local bytes_out=$(echo "$line" | awk '{print $4}' | sed 's/[^0-9]//g')
            
            # Convert to MB/s (rough estimation)
            local total_mb=$(( (bytes_in + bytes_out) / 1024 / 1024 / monitoring_duration ))
            
            if [[ $total_mb -gt ${BANDWIDTH_THRESHOLDS["moderate"]} ]]; then
                high_bandwidth_processes="$high_bandwidth_processes$process_name:${total_mb}MB/s,"
            fi
        done < "$analysis_file"
    fi
    
    log_action "Bandwidth analysis completed. High usage processes: ${high_bandwidth_processes%,}"
    echo "${high_bandwidth_processes%,}"
}

# Security threat detection
detect_security_threats() {
    local scan_mode="$1"
    local threats_file="$MONITORING_DIR/security_threats_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Starting security threat detection: $scan_mode"
    
    # Get network connections
    local connections=$(lsof -nPi 2>/dev/null)
    
    # Suspicious patterns
    local suspicious_ports=("22" "23" "3389" "5900" "6667" "6697" "1337" "31337")
    local suspicious_domains=("*.tor" "*.onion" "tempmail" "guerrillamail" "10minutemail")
    local suspicious_processes=("nc" "netcat" "telnet" "ssh" "tor")
    
    local threats_detected=""
    local threat_count=0
    
    # Check for suspicious ports
    for port in "${suspicious_ports[@]}"; do
        local port_connections=$(echo "$connections" | grep ":$port" | wc -l)
        if [[ $port_connections -gt 0 ]]; then
            threats_detected="$threats_detected{\"type\":\"suspicious_port\",\"details\":\"Port $port has $port_connections connections\",\"severity\":\"medium\"},"
            ((threat_count++))
        fi
    done
    
    # Check for suspicious processes
    for process in "${suspicious_processes[@]}"; do
        if pgrep -f "$process" >/dev/null 2>&1; then
            threats_detected="$threats_detected{\"type\":\"suspicious_process\",\"details\":\"Process $process is running\",\"severity\":\"high\"},"
            ((threat_count++))
        fi
    done
    
    # Check for unusual connection patterns
    local unique_external_ips=$(echo "$connections" | grep -E ":[0-9]+->.*:[0-9]+" | awk -F'->' '{print $2}' | cut -d':' -f1 | sort | uniq | wc -l)
    if [[ $unique_external_ips -gt 50 ]]; then
        threats_detected="$threats_detected{\"type\":\"connection_anomaly\",\"details\":\"Unusual number of external connections: $unique_external_ips\",\"severity\":\"medium\"},"
        ((threat_count++))
    fi
    
    # Remove trailing comma
    threats_detected="${threats_detected%,}"
    
    cat > "$threats_file" << EOF
{
  "security_scan": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "scan_mode": "$scan_mode",
    "threats_detected": $threat_count,
    "threats": [$threats_detected]
  },
  "network_summary": {
    "total_connections": $(echo "$connections" | wc -l),
    "unique_processes": $(echo "$connections" | cut -f1 -d' ' | sort | uniq | wc -l),
    "external_connections": $unique_external_ips
  }
}
EOF
    
    if [[ $threat_count -gt 0 ]]; then
        log_action "SECURITY ALERT: $threat_count threats detected. Report: $threats_file"
        
        # Create alert
        echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):SECURITY_THREAT:$threat_count threats detected" >> "$ALERTS_DIR/security_alerts.log"
    else
        log_action "Security scan completed. No threats detected."
    fi
    
    echo "$threats_file"
}

# Apply network monitoring policy
apply_monitoring_policy() {
    local policy="$1"
    
    if [[ -z "${MONITORING_POLICIES[$policy]}" ]]; then
        log_action "ERROR: Unknown monitoring policy: $policy"
        return 1
    fi
    
    log_action "Applying network monitoring policy: $policy"
    
    # Parse policy string
    IFS=',' read -ra policy_items <<< "${MONITORING_POLICIES[$policy]}"
    
    local policy_config="$MONITORING_DIR/active_policy.conf"
    echo "# Roundfleet Network Monitoring Policy: $policy" > "$policy_config"
    echo "# Applied: $(date)" >> "$policy_config"
    echo "" >> "$policy_config"
    
    for item in "${policy_items[@]}"; do
        IFS=':' read -ra parts <<< "$item"
        local category="${parts[0]}"
        local action="${parts[1]}"
        
        echo "$category=$action" >> "$policy_config"
        
        case "$action" in
            "blocked")
                log_action "Configuring blocks for category: $category"
                # In a real implementation, this would configure firewall rules
                ;;
            "monitored")
                log_action "Enhanced monitoring for category: $category"
                ;;
            "priority")
                log_action "Priority bandwidth for category: $category"
                ;;
            "allowed")
                log_action "Standard access for category: $category"
                ;;
        esac
    done
    
    log_action "Network monitoring policy '$policy' applied successfully"
    
    # Generate policy compliance report
    generate_compliance_report "$policy"
}

# Real-time network monitoring
start_realtime_monitoring() {
    local monitoring_interval="$1"
    local alert_threshold="$2"
    
    log_action "Starting real-time network monitoring (interval: ${monitoring_interval}s, threshold: $alert_threshold connections)"
    
    local monitor_file="$MONITORING_DIR/realtime_monitor.log"
    
    while true; do
        local current_connections=$(lsof -nPi 2>/dev/null | wc -l)
        local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
        local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
        
        echo "$timestamp:$current_connections:$unique_processes" >> "$monitor_file"
        
        # Check alert threshold
        if [[ $current_connections -gt $alert_threshold ]]; then
            log_action "ALERT: High network activity detected - $current_connections connections"
            echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):HIGH_ACTIVITY:$current_connections connections" >> "$ALERTS_DIR/activity_alerts.log"
        fi
        
        sleep "$monitoring_interval"
    done
}

# Network access control
control_network_access() {
    local action="$1"
    local target="$2"
    local reason="$3"
    
    log_action "Network access control: $action for $target (Reason: $reason)"
    
    case "$action" in
        "block_process")
            # Kill network-connected processes
            local pids=$(pgrep -f "$target" 2>/dev/null)
            for pid in $pids; do
                if kill -TERM "$pid" 2>/dev/null; then
                    log_action "Terminated process: $target (PID: $pid)"
                fi
            done
            ;;
        "block_domain")
            # Add to hosts file for blocking
            if ! grep -q "127.0.0.1 $target" /etc/hosts; then
                echo "127.0.0.1 $target" >> /etc/hosts
                log_action "Blocked domain: $target"
            fi
            ;;
        "unblock_domain")
            # Remove from hosts file
            sed -i "" "/127.0.0.1 $target/d" /etc/hosts
            log_action "Unblocked domain: $target"
            ;;
        "limit_bandwidth")
            # This would require integration with traffic shaping tools
            log_action "Bandwidth limiting requested for: $target (Not implemented - requires pfctl or similar)"
            ;;
    esac
    
    # Record action in audit log
    echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):$action:$target:$reason:$(whoami)" >> "$AUDIT_DIR/network_control_actions.log"
}

# Generate comprehensive compliance report
generate_compliance_report() {
    local policy="$1"
    local report_file="$REPORTS_DIR/network_monitoring_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    # Get current network activity
    local active_connections=$(lsof -nPi 2>/dev/null | wc -l)
    local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
    
    # Count alerts
    local security_alerts=0
    local activity_alerts=0
    
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        security_alerts=$(wc -l < "$ALERTS_DIR/security_alerts.log")
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        activity_alerts=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
    fi
    
    cat > "$report_file" << EOF
{
  "report_metadata": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "policy_applied": "$policy",
    "report_version": "1.0"
  },
  "network_monitoring_status": {
    "active_connections": $active_connections,
    "monitored_processes": $unique_processes,
    "security_alerts": $security_alerts,
    "activity_alerts": $activity_alerts,
    "monitoring_active": $([ -f "$MONITORING_DIR/realtime_monitor.log" ] && echo "true" || echo "false")
  },
  "security_policy": {
    "name": "$policy",
    "categories_monitored": $(echo "${!APP_CATEGORIES[@]}" | wc -w),
    "compliance_frameworks": ["SOX", "HIPAA", "NIST", "ISO27001", "PCI-DSS"]
  },
  "network_health": {
    "bandwidth_monitoring": $(command -v nettop >/dev/null && echo "true" || echo "false"),
    "firewall_active": $(pfctl -s info 2>/dev/null | grep -q "Status: Enabled" && echo "true" || echo "false"),
    "dns_filtering": $(networksetup -getdnsservers Wi-Fi | grep -q "208.67" && echo "true" || echo "false"),
    "vpn_detected": $(ifconfig | grep -q "utun" && echo "true" || echo "false")
  },
  "compliance_metrics": {
    "policy_violations": 0,
    "data_exfiltration_attempts": 0,
    "unauthorized_connections": $security_alerts,
    "bandwidth_violations": 0
  }
}
EOF
    
    log_action "Network monitoring compliance report generated: $report_file"
    echo "Report saved to: $report_file"
}

# Health check and system validation
perform_health_check() {
    echo "=== Roundfleet Network Monitoring Health Check ==="
    
    # Check network monitoring tools
    local tools=("lsof" "netstat" "nettop" "networksetup")
    for tool in "${tools[@]}"; do
        if command -v "$tool" >/dev/null 2>&1; then
            echo "✓ $tool: Available"
        else
            echo "✗ $tool: Missing"
        fi
    done
    
    # Check active connections
    local connections=$(lsof -nPi 2>/dev/null | wc -l)
    echo "✓ Active network connections: $connections"
    
    # Check monitoring files
    if [[ -f "$MONITORING_DIR/active_policy.conf" ]]; then
        local active_policy=$(grep -v "^#" "$MONITORING_DIR/active_policy.conf" | head -1)
        echo "✓ Active monitoring policy: $active_policy"
    else
        echo "○ No active monitoring policy"
    fi
    
    # Check for alerts
    local total_alerts=0
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        local security_count=$(wc -l < "$ALERTS_DIR/security_alerts.log")
        total_alerts=$((total_alerts + security_count))
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        local activity_count=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
        total_alerts=$((total_alerts + activity_count))
    fi
    
    if [[ $total_alerts -gt 0 ]]; then
        echo "⚠️  Total alerts: $total_alerts"
    else
        echo "✓ No active alerts"
    fi
    
    # Check system network health
    local network_interfaces=$(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
    echo "✓ Network interfaces: $network_interfaces"
    
    # Check DNS configuration
    local dns_servers=$(networksetup -getdnsservers Wi-Fi 2>/dev/null | head -1)
    echo "✓ DNS server: $dns_servers"
}

# Fleet deployment function
deploy_to_fleet() {
    local policy="$1"
    local fleet_file="$2"
    
    if [[ ! -f "$fleet_file" ]]; then
        log_action "ERROR: Fleet file not found: $fleet_file"
        return 1
    fi
    
    log_action "Starting fleet deployment of network monitoring policy: $policy"
    
    while IFS= read -r host; do
        [[ -z "$host" || "$host" =~ ^#.*$ ]] && continue
        
        echo "Deploying to: $host"
        
        # Copy this script to remote host and execute
        ssh "$host" "bash -s" << EOF
#!/bin/bash
# Remote deployment of network monitoring policy: $policy

# Create directories
mkdir -p /etc/roundfleet/{network_monitoring,reports,compliance,audit,alerts}

# Apply the policy (simplified for remote execution)
$(declare -p APP_CATEGORIES)
$(declare -p MONITORING_POLICIES)
$(type apply_monitoring_policy | sed '1d')

apply_monitoring_policy "$policy"
EOF
        
        if [[ $? -eq 0 ]]; then
            log_action "Successfully deployed to: $host"
        else
            log_action "Failed to deploy to: $host"
        fi
        
    done < "$fleet_file"
    
    log_action "Fleet deployment completed"
}

# Main execution function
main() {
    create_directories
    
    case "${1:-}" in
        "monitor_activity")
            get_network_activity "${2:-standard}"
            ;;
        "analyze_bandwidth")
            analyze_bandwidth_usage "${2:-30}"
            ;;
        "detect_threats")
            detect_security_threats "${2:-standard}"
            ;;
        "apply_policy")
            apply_monitoring_policy "$2"
            ;;
        "realtime_monitor")
            start_realtime_monitoring "${2:-10}" "${3:-100}"
            ;;
        "control_access")
            control_network_access "$2" "$3" "${4:-manual}"
            ;;
        "health_check")
            perform_health_check
            ;;
        "report")
            generate_compliance_report "${2:-manual}"
            ;;
        "deploy")
            deploy_to_fleet "$2" "$3"
            ;;
        "help"|*)
            echo "Roundfleet Enterprise Network Monitoring System"
            echo ""
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  monitor_activity [level]            - Monitor network activity (standard|detailed|security)"
            echo "  analyze_bandwidth [duration]        - Analyze bandwidth usage for duration in seconds"
            echo "  detect_threats [mode]               - Detect security threats (standard|strict|paranoid)"
            echo "  apply_policy <policy>               - Apply monitoring policy (strict_monitoring|balanced_monitoring|minimal_monitoring|development_focused|security_lockdown)"
            echo "  realtime_monitor [interval] [threshold] - Start real-time monitoring"
            echo "  control_access <action> <target> [reason] - Control network access (block_process|block_domain|unblock_domain|limit_bandwidth)"
            echo "  health_check                        - Perform system health check"
            echo "  report [policy]                     - Generate compliance report"
            echo "  deploy <policy> <fleet_file>        - Deploy policy to fleet"
            echo ""
            echo "Examples:"
            echo "  $0 monitor_activity detailed"
            echo "  $0 analyze_bandwidth 60"
            echo "  $0 detect_threats strict"
            echo "  $0 apply_policy strict_monitoring"
            echo "  $0 control_access block_domain malicious-site.com"
            echo "  $0 health_check"
            ;;
    esac
}

# Execute main function
main "$@"

Network Monitoring Categories

The enterprise system monitors applications across different categories:

CategoryApplicationsMonitoring Level
Business AppsSlack, Zoom, Microsoft Teams, Office 365Standard monitoring
Development ToolsXcode, Visual Studio Code, Docker, GitEnhanced logging
BrowsersChrome, Firefox, Safari, EdgeTraffic analysis
CommunicationMail, Messages, FaceTime, SkypeSecurity scanning
Cloud StorageDropbox, Google Drive, OneDriveData transfer monitoring
EntertainmentSpotify, Netflix, YouTube, SteamBandwidth limiting
Security Tools1Password, Little Snitch, WiresharkPriority access
System Serviceslocationd, cloudd, nsurlsessiondSystem health monitoring

Advanced Network Analysis

Real-time Bandwidth Monitoring

# Monitor bandwidth usage for 60 seconds
./network_monitor.sh analyze_bandwidth 60

# Check for high-bandwidth processes
nettop -P -t wifi -l 1 | head -20

Security Threat Detection

# Run security threat scan
./network_monitor.sh detect_threats strict

# Check for suspicious connections
lsof -nPi | grep -E ":(22|23|3389|5900|6667)"

Connection Analysis

# Detailed connection analysis
lsof -nPi | awk '{print $1, $8, $9}' | sort | uniq -c | sort -nr

# Monitor specific application
lsof -nPi | grep -i "chrome"

Policy Implementation

Apply Enterprise Monitoring Policy

# Strict monitoring for secure environments
./network_monitor.sh apply_policy strict_monitoring

# Balanced monitoring for general use
./network_monitor.sh apply_policy balanced_monitoring

# Development-focused monitoring
./network_monitor.sh apply_policy development_focused

Network Access Control

# Block suspicious process
./network_monitor.sh control_access block_process "suspicious_app" "security_violation"

# Block malicious domain
./network_monitor.sh control_access block_domain "malicious-site.com" "threat_detected"

# Unblock domain after verification
./network_monitor.sh control_access unblock_domain "example.com" "false_positive"

Enterprise Features

Automated Threat Response

The system can automatically respond to threats:

  • Block suspicious processes
  • Quarantine network connections
  • Alert security teams
  • Generate incident reports

Bandwidth Management

Monitor and control bandwidth usage:

  • Identify bandwidth-heavy applications
  • Implement quality of service (QoS) rules
  • Generate usage reports
  • Alert on excessive consumption

Compliance Monitoring

Track network activity for compliance:

  • Log all network connections
  • Monitor data transfer volumes
  • Detect policy violations
  • Generate audit reports

Important Security Considerations

  • Real-time monitoring requires appropriate system resources
  • Network analysis should respect user privacy policies
  • Threat detection may generate false positives requiring validation
  • Access controls should include emergency override procedures
  • Audit logging must be protected from unauthorized access

Compliance and Reporting

The enterprise system provides comprehensive audit trails for:

  • SOX Compliance - Financial data network access controls
  • HIPAA Requirements - Healthcare information transmission monitoring
  • PCI-DSS Standards - Payment card industry network security
  • NIST Framework - Cybersecurity network monitoring standards
  • ISO 27001 - Information security network management

Testing and Validation

Before enterprise deployment:

  1. Test monitoring accuracy with known network activities
  2. Verify threat detection effectiveness and false positive rates
  3. Confirm policy enforcement works as expected
  4. Test emergency procedures and override mechanisms
  5. Validate compliance reporting completeness and accuracy

This comprehensive system transforms basic network monitoring into an enterprise-grade security and management platform with advanced threat detection, policy enforcement, and fleet deployment capabilities.

Retrieve Network Information on macOS

Collect detailed network information from your Roundfleet devices using command-line tools. This tutorial covers MAC address discovery, IP configuration, port monitoring, and network diagnostics for comprehensive fleet management.

Understanding macOS Network Information

macOS provides several command-line utilities for network information gathering:

  • networksetup - Hardware port and network configuration management
  • ifconfig - Network interface configuration and status
  • netstat - Network connections and port information
  • arp - Address Resolution Protocol table management
  • ipconfig - IP address and DHCP configuration

Retrieve MAC Addresses

List All Hardware Ports

#!/bin/bash

# Display all network hardware ports and their MAC addresses
networksetup -listallhardwareports

echo "Hardware port information retrieved successfully"

Get Specific Interface MAC Address

#!/bin/bash

# Get MAC address for specific interface (Wi-Fi)
echo "Wi-Fi Interface (en0) MAC Address:"
networksetup -getmacaddress en0

echo -e "\nEthernet Interface (en1) MAC Address:"
networksetup -getmacaddress en1

echo -e "\nThunderbolt Bridge (bridge0) MAC Address:"
networksetup -getmacaddress bridge0 2>/dev/null || echo "Thunderbolt Bridge not available"

Comprehensive MAC Address Report

#!/bin/bash

# Generate detailed MAC address report
echo "=== Roundfleet Network Hardware Report ==="
echo "Device: $(hostname)"
echo "Date: $(date)"
echo "========================================="

# Get all hardware ports
echo -e "\n📡 Network Hardware Inventory:"
networksetup -listallhardwareports

echo -e "\n🔍 Primary Interface Details:"
echo "Wi-Fi (en0): $(networksetup -getmacaddress en0 | awk '{print $3}')"
echo "Ethernet (en1): $(networksetup -getmacaddress en1 | awk '{print $3}' 2>/dev/null || echo 'Not available')"

# Check for additional interfaces
echo -e "\n🌐 Additional Interfaces:"
for i in {2..5}; do
    mac_addr=$(networksetup -getmacaddress en$i 2>/dev/null | awk '{print $3}')
    if [[ -n "$mac_addr" && "$mac_addr" != "not" ]]; then
        echo "en$i: $mac_addr"
    fi
done

Discover IP Addresses

Basic IP Address Retrieval

#!/bin/bash

# Get IP address for Wi-Fi interface
WIFI_IP=$(ipconfig getifaddr en0 2>/dev/null)
ETHERNET_IP=$(ipconfig getifaddr en1 2>/dev/null)

echo "Network IP Addresses:"
echo "Wi-Fi (en0): ${WIFI_IP:-Not connected}"
echo "Ethernet (en1): ${ETHERNET_IP:-Not connected}"

Comprehensive IP Configuration

#!/bin/bash

# Detailed IP configuration report
echo "=== Roundfleet IP Configuration Report ==="
echo "Device: $(hostname)"
echo "Timestamp: $(date)"
echo "========================================"

# Active network interfaces
echo -e "\n🌐 Active Network Interfaces:"
for interface in en0 en1 en2 en3; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        echo "$interface: $ip_addr"
        
        # Get additional details for active interfaces
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        router=$(ipconfig getoption $interface router 2>/dev/null)
        dns_servers=$(ipconfig getoption $interface domain_name_server 2>/dev/null)
        
        echo "  Subnet: ${subnet_mask:-N/A}"
        echo "  Gateway: ${router:-N/A}"
        echo "  DNS: ${dns_servers:-N/A}"
        echo ""
    fi
done

# Public IP address
echo "🌍 External IP Address:"
curl -s ifconfig.me 2>/dev/null || echo "Unable to retrieve external IP"

Network Interface Status

#!/bin/bash

# Monitor network interface status
echo "=== Network Interface Status Monitor ==="

# Get interface statistics
echo -e "\n📊 Interface Statistics:"
ifconfig | grep -E "(en[0-9]:|inet |status:|media:)" | while read line; do
    echo "$line"
done

echo -e "\n🔄 DHCP Lease Information:"
for interface in en0 en1; do
    lease_info=$(ipconfig getpacket $interface 2>/dev/null)
    if [[ -n "$lease_info" ]]; then
        echo "Interface $interface:"
        echo "$lease_info" | grep -E "(lease_time|server_identifier|domain_name)"
        echo ""
    fi
done

Analyze Network Configuration

Complete Network Overview

#!/bin/bash

# Comprehensive network configuration analysis
echo "=== Complete Network Overview ==="
ifconfig

echo -e "\n🔍 Network Summary:"
ifconfig | grep -E "^[a-z]" | while read line; do
    interface=$(echo $line | cut -d: -f1)
    status=$(ifconfig $interface | grep "status:" | cut -d' ' -f2-)
    echo "$interface: ${status:-active}"
done

Network Services and DNS

#!/bin/bash

# Network services and DNS configuration
echo "=== Network Services Configuration ==="

echo "🌐 DNS Configuration:"
echo "System DNS Servers:"
scutil --dns | grep "nameserver" | head -5

echo -e "\n📡 Network Services:"
networksetup -listallnetworkservices

echo -e "\n🔍 Active Network Service Details:"
active_service=$(networksetup -listallnetworkservices | grep -v "asterisk" | head -2 | tail -1)
if [[ -n "$active_service" ]]; then
    echo "Service: $active_service"
    networksetup -getinfo "$active_service"
fi

Subnet and Routing Information

#!/bin/bash

# Subnet mask and routing information
echo "=== Routing and Subnet Information ==="

echo "🛣️  Routing Table:"
netstat -rn | head -10

echo -e "\n🔍 Interface Subnet Details:"
for interface in en0 en1; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        echo "$interface: $ip_addr/${subnet_mask:-unknown}"
    fi
done

Monitor Port Information

Active TCP Connections

#!/bin/bash

# Display active TCP connections
echo "=== Active TCP Connections ==="
netstat -ap TCP

echo -e "\n📊 Connection Summary:"
echo "Total connections: $(netstat -ap TCP | grep -c ESTABLISHED)"
echo "Listening ports: $(netstat -ap TCP | grep -c LISTEN)"
echo "Time-wait connections: $(netstat -ap TCP | grep -c TIME_WAIT)"

Listening Ports Analysis

#!/bin/bash

# Analyze listening ports
echo "=== Listening Ports Analysis ==="

echo "🔍 All Listening Ports:"
netstat -a | grep -i "LISTEN"

echo -e "\n📋 Listening Ports Summary:"
netstat -a | grep -i "LISTEN" | awk '{print $4}' | cut -d. -f2 | sort -n | uniq -c | sort -nr

echo -e "\n🔒 Security-Relevant Ports:"
netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995|587|25|53|21|23) "

Port Monitoring Script

#!/bin/bash

# Comprehensive port monitoring
LOG_FILE="/var/log/roundfleet_ports.log"

monitor_ports() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    {
        echo "=== Port Monitoring Report ==="
        echo "Timestamp: $timestamp"
        echo "Device: $(hostname)"
        echo "================================"
        
        echo -e "\n🔍 Current Listening Ports:"
        netstat -a | grep -i "LISTEN" | head -20
        
        echo -e "\n📊 Connection Statistics:"
        echo "ESTABLISHED: $(netstat -ap TCP | grep -c ESTABLISHED)"
        echo "LISTEN: $(netstat -ap TCP | grep -c LISTEN)"
        echo "TIME_WAIT: $(netstat -ap TCP | grep -c TIME_WAIT)"
        echo "CLOSE_WAIT: $(netstat -ap TCP | grep -c CLOSE_WAIT)"
        
        echo -e "\n🚨 Suspicious Connections:"
        netstat -ap TCP | grep -E ":(6667|6697|8080|9050|4444|31337)" || echo "None detected"
        
    } | tee -a "$LOG_FILE"
}

# Execute monitoring
monitor_ports

Display ARP Table

Basic ARP Information

#!/bin/bash

# Display Address Resolution Protocol table
arp -a

echo "ARP table retrieved successfully"

Detailed ARP Analysis

#!/bin/bash

# Comprehensive ARP table analysis
echo "=== ARP Table Analysis ==="
echo "Device: $(hostname)"
echo "Date: $(date)"
echo "=========================="

echo -e "\n🔍 Complete ARP Table:"
arp -a

echo -e "\n📊 ARP Statistics:"
total_entries=$(arp -a | wc -l)
incomplete_entries=$(arp -a | grep -c "incomplete")
complete_entries=$((total_entries - incomplete_entries))

echo "Total ARP entries: $total_entries"
echo "Complete entries: $complete_entries"
echo "Incomplete entries: $incomplete_entries"

echo -e "\n🌐 Network Neighbors:"
arp -a | head -10 | while read line; do
    hostname=$(echo $line | cut -d' ' -f1)
    ip=$(echo $line | cut -d'(' -f2 | cut -d')' -f1)
    mac=$(echo $line | cut -d' ' -f4)
    echo "$ip -> $mac ($hostname)"
done

ARP Security Check

#!/bin/bash

# ARP table security analysis
echo "=== ARP Security Analysis ==="

# Check for duplicate MAC addresses (potential ARP spoofing)
echo "🔒 Duplicate MAC Address Check:"
arp -a | awk '{print $4}' | sort | uniq -d | while read mac; do
    if [[ -n "$mac" ]]; then
        echo "⚠️  Duplicate MAC detected: $mac"
        arp -a | grep "$mac"
    fi
done

# Check for suspicious patterns
echo -e "\n🚨 Security Alerts:"
suspicious_count=$(arp -a | grep -c "incomplete")
if [[ $suspicious_count -gt 10 ]]; then
    echo "⚠️  High number of incomplete ARP entries: $suspicious_count"
fi

# Network vendor analysis
echo -e "\n🏢 Network Vendor Analysis:"
arp -a | grep -E "([0-9a-f]{2}:){5}[0-9a-f]{2}" | awk '{print $4}' | cut -d: -f1-3 | sort | uniq -c | sort -nr | head -5

Enterprise Network Monitoring Script

#!/bin/bash

# Roundfleet Enterprise Network Monitoring Suite
LOG_FILE="/var/log/roundfleet_network.log"
REPORT_FILE="/tmp/network_report_$(date +%Y%m%d_%H%M%S).txt"

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Generate comprehensive network report
generate_network_report() {
    {
        echo "Roundfleet Network Assessment Report"
        echo "Generated: $(date)"
        echo "Device: $(hostname)"
        echo "User: $(whoami)"
        echo "OS Version: $(sw_vers -productVersion)"
        echo "=========================================="
        echo ""
        
        # Hardware inventory
        echo "🔧 Network Hardware:"
        networksetup -listallhardwareports
        echo ""
        
        # IP configuration
        echo "🌐 IP Configuration:"
        for interface in en0 en1 en2; do
            ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
            if [[ -n "$ip_addr" ]]; then
                echo "$interface: $ip_addr"
                mac_addr=$(networksetup -getmacaddress $interface | awk '{print $3}')
                echo "  MAC: $mac_addr"
                
                subnet=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
                router=$(ipconfig getoption $interface router 2>/dev/null)
                echo "  Subnet: ${subnet:-N/A}"
                echo "  Gateway: ${router:-N/A}"
                echo ""
            fi
        done
        
        # Network services
        echo "📡 Network Services:"
        networksetup -listallnetworkservices | grep -v "asterisk"
        echo ""
        
        # DNS configuration
        echo "🔍 DNS Configuration:"
        scutil --dns | grep "nameserver" | head -3
        echo ""
        
        # Security assessment
        echo "🔒 Security Assessment:"
        listening_ports=$(netstat -a | grep -c "LISTEN")
        established_connections=$(netstat -ap TCP | grep -c ESTABLISHED)
        echo "Listening ports: $listening_ports"
        echo "Active connections: $established_connections"
        
        # Check for common security ports
        security_ports=$(netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995)" | wc -l)
        echo "Security-relevant ports: $security_ports"
        
        echo ""
        echo "Report completed at: $(date)"
        
    } > "$REPORT_FILE"
    
    echo "📊 Network report generated: $REPORT_FILE"
}

# Network connectivity test
test_connectivity() {
    echo "=== Network Connectivity Test ==="
    
    # Test DNS resolution
    if nslookup google.com > /dev/null 2>&1; then
        echo "✅ DNS resolution: Working"
    else
        echo "❌ DNS resolution: Failed"
    fi
    
    # Test internet connectivity
    if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
        echo "✅ Internet connectivity: Working"
    else
        echo "❌ Internet connectivity: Failed"
    fi
    
    # Test local gateway
    gateway=$(route -n get default | grep gateway | awk '{print $2}')
    if [[ -n "$gateway" ]] && ping -c 1 "$gateway" > /dev/null 2>&1; then
        echo "✅ Gateway connectivity: Working ($gateway)"
    else
        echo "❌ Gateway connectivity: Failed"
    fi
}

# Main execution
main() {
    log_action "=== Roundfleet Network Monitoring Started ==="
    
    generate_network_report
    echo ""
    test_connectivity
    
    log_action "Network monitoring completed. Report: $REPORT_FILE"
}

# Execute main function
main "$@"

Network Information Reference

Common Network Interfaces

InterfaceDescriptionCommon Usage
en0Primary network interfaceWi-Fi connection
en1Secondary interfaceEthernet connection
en2-en5Additional interfacesUSB adapters, Thunderbolt
lo0Loopback interfaceLocal system communication
bridge0Thunderbolt bridgeDevice-to-device connections
utun0-utun3Tunnel interfacesVPN connections

Network Commands Quick Reference

# Get interface IP
ipconfig getifaddr en0

# Get interface configuration
ipconfig getoption en0 subnet_mask
ipconfig getoption en0 router
ipconfig getoption en0 domain_name_server

# Network hardware
networksetup -listallhardwareports
networksetup -getmacaddress en0

# Interface status
ifconfig en0
ifconfig -a

# Network connections
netstat -rn          # Routing table
netstat -i           # Interface statistics
netstat -ap TCP      # TCP connections

# ARP operations
arp -a               # Show ARP table
arp -d hostname      # Delete ARP entry

Advanced Network Diagnostics

Network Performance Testing

#!/bin/bash

# Network performance diagnostics
echo "=== Network Performance Diagnostics ==="

# Interface statistics
echo "📊 Interface Statistics:"
netstat -i

# Bandwidth monitoring
echo -e "\n🚀 Network Activity (10 seconds):"
if command -v nettop >/dev/null 2>&1; then
    timeout 10 nettop -l 1 -J bytes_in,bytes_out -P
else
    echo "nettop not available, using netstat"
    netstat -i
fi

# Latency testing
echo -e "\n⏱️  Latency Tests:"
echo "Google DNS (8.8.8.8):"
ping -c 3 8.8.8.8 | tail -1

echo "Cloudflare DNS (1.1.1.1):"
ping -c 3 1.1.1.1 | tail -1

Wireless Network Information

#!/bin/bash

# Wireless network detailed information
echo "=== Wireless Network Analysis ==="

# Current Wi-Fi information
current_wifi=$(networksetup -getairportnetwork en0)
echo "Current Wi-Fi: $current_wifi"

# Wi-Fi power status
wifi_power=$(networksetup -getairportpower en0)
echo "Wi-Fi Power: $wifi_power"

# Available networks (requires admin privileges)
echo -e "\n📡 Available Networks:"
if [[ $EUID -eq 0 ]]; then
    airport -s 2>/dev/null || echo "Airport utility not available"
else
    echo "Admin privileges required for network scanning"
fi

# Wi-Fi interface details
echo -e "\n🔍 Wi-Fi Interface Details:"
ifconfig en0 | grep -E "(inet|ether|status)"

Important Notes

  • Interface names may vary between macOS versions and hardware
  • Administrative privileges required for some network operations
  • Security implications - Monitor open ports and connections regularly
  • Performance impact - Network monitoring scripts may affect system performance
  • Privacy considerations - ARP tables contain information about network neighbors

Troubleshooting

Common Network Issues

No IP Address:

# Renew DHCP lease
sudo ipconfig set en0 DHCP

DNS Resolution Problems:

# Flush DNS cache
sudo dscacheutil -flushcache

Interface Not Responding:

# Reset network interface
sudo ifconfig en0 down
sudo ifconfig en0 up

Remember to test these scripts on individual devices before deploying across your Roundfleet environment.

Menu Bar Customization and Icon Management on macOS

Customize menu bar appearance and manage system icons across your Roundfleet devices. This tutorial covers icon visibility control, user interface optimization, and enterprise-grade menu bar management for improved user experience and organizational consistency.

Understanding Menu Bar Management

The macOS menu bar contains various system indicators and quick access icons:

  • Network indicators - VPN, Wi-Fi, Bluetooth status
  • System monitors - Battery, volume, date/time
  • Application icons - Third-party app status indicators
  • User controls - Spotlight, Control Center, Siri
  • Corporate tools - MDM agents, security software

Basic VPN Icon Management

Hide VPN Icon from Menu Bar

#!/bin/bash

# Hide VPN icon from menu bar
hide_vpn_icon() {
    echo "=== Hiding VPN Icon from Menu Bar ==="
    
    # Get current user
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Current user: $currentUser"
    
    # Function to run commands as current user
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Remove VPN menu extra
    if runAsUser /usr/libexec/PlistBuddy -c 'delete menuExtras: "/System/Library/CoreServices/Menu Extras/VPN.menu"' "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ VPN menu entry removed"
    else
        echo "⚠️  VPN menu entry not found or already removed"
    fi
    
    # Restart system services to apply changes
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "🔄 System UI refreshed"
    echo "✅ VPN icon hidden from menu bar"
}

# Execute function
hide_vpn_icon

Show VPN Icon in Menu Bar

#!/bin/bash

# Show VPN icon in menu bar
show_vpn_icon() {
    echo "=== Adding VPN Icon to Menu Bar ==="
    
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Current user: $currentUser"
    
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Add VPN menu extra
    local vpn_path="/System/Library/CoreServices/Menu Extras/VPN.menu"
    if runAsUser /usr/libexec/PlistBuddy -c "add menuExtras: string '$vpn_path'" "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ VPN menu entry added"
    else
        echo "⚠️  VPN menu entry already exists"
    fi
    
    # Restart system services
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "✅ VPN icon shown in menu bar"
}

# Execute function
show_vpn_icon

Enterprise Menu Bar Management System

#!/bin/bash

# Roundfleet Enterprise Menu Bar Management System
# Comprehensive interface customization, user experience optimization, and fleet deployment

# Configuration
LOG_FILE="/var/log/roundfleet_menubar.log"
CONFIG_DIR="/etc/roundfleet/interface"
PROFILES_DIR="$CONFIG_DIR/profiles"
BACKUP_DIR="/var/backups/menubar_configs"
REPORTS_DIR="$CONFIG_DIR/reports"

# Available menu extras
declare -A MENU_EXTRAS=(
    ["vpn"]="/System/Library/CoreServices/Menu Extras/VPN.menu"
    ["wifi"]="/System/Library/CoreServices/Menu Extras/AirPort.menu"
    ["bluetooth"]="/System/Library/CoreServices/Menu Extras/Bluetooth.menu"
    ["volume"]="/System/Library/CoreServices/Menu Extras/Volume.menu"
    ["battery"]="/System/Library/CoreServices/Menu Extras/Battery.menu"
    ["clock"]="/System/Library/CoreServices/Menu Extras/Clock.menu"
    ["displays"]="/System/Library/CoreServices/Menu Extras/Displays.menu"
    ["timemachine"]="/System/Library/CoreServices/Menu Extras/TimeMachine.menu"
    ["textinput"]="/System/Library/CoreServices/Menu Extras/TextInput.menu"
    ["script"]="/System/Library/CoreServices/Menu Extras/Script Menu.menu"
)

# Profile configurations
declare -A MENU_PROFILES=(
    ["minimal"]="clock,battery,wifi"
    ["standard"]="clock,battery,wifi,volume,bluetooth"
    ["full"]="clock,battery,wifi,volume,bluetooth,displays,vpn"
    ["corporate"]="clock,battery,wifi,vpn,timemachine"
    ["education"]="clock,battery,wifi,volume,textinput"
    ["kiosk"]="clock,battery"
    ["developer"]="clock,battery,wifi,volume,bluetooth,displays,script"
    ["secure"]="clock,battery,wifi"
)

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Setup directories
setup_directories() {
    for dir in "$CONFIG_DIR" "$PROFILES_DIR" "$BACKUP_DIR" "$REPORTS_DIR"; do
        if [[ ! -d "$dir" ]]; then
            mkdir -p "$dir"
            log_action "Created directory: $dir"
        fi
    done
}

# Get current user
get_current_user() {
    local user
    user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$user" == "loginwindow" || -z "$user" ]]; then
        return 1
    fi
    
    echo "$user"
    return 0
}

# Execute command as current user
run_as_user() {
    local user="$1"
    shift
    
    local userID
    userID=$(id -u "$user" 2>/dev/null) || return 1
    
    /bin/launchctl asuser "$userID" sudo -u "$user" "$@"
}

# Get current menu bar configuration
get_current_menubar_config() {
    local user="$1"
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    
    if [[ ! -f "$plist_path" ]]; then
        echo "[]"
        return 1
    fi
    
    # Extract current menu extras
    local menu_extras
    menu_extras=$(run_as_user "$user" /usr/libexec/PlistBuddy -c "print menuExtras:" "$plist_path" 2>/dev/null | grep -E "\.menu$" | sed 's/^[ ]*//' || echo "")
    
    if [[ -z "$menu_extras" ]]; then
        echo "[]"
    else
        echo "$menu_extras" | jq -R -s 'split("\n") | map(select(length > 0))'
    fi
}

# Apply menu bar profile
apply_menubar_profile() {
    local profile_name="$1"
    local target_user="$2"
    
    log_action "Applying menu bar profile: $profile_name"
    
    # Get profile configuration
    local profile_config="${MENU_PROFILES[$profile_name]}"
    if [[ -z "$profile_config" ]]; then
        log_action "❌ Unknown profile: $profile_name"
        return 1
    fi
    
    # Get target users
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Get all users with UID >= 500
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Apply profile to each user
    for user in "${users[@]}"; do
        log_action "Configuring menu bar for user: $user"
        
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Backup current configuration
        backup_user_menubar_config "$user"
        
        # Clear existing menu extras
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Add profile menu items
        IFS=',' read -ra ITEMS <<< "$profile_config"
        local index=0
        
        for item in "${ITEMS[@]}"; do
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                log_action "Added menu item: $item for user: $user"
                ((index++))
            else
                log_action "⚠️  Menu item not found: $item"
            fi
        done
        
        # Restart UI services
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Profile '$profile_name' applied to user: $user"
    done
    
    return 0
}

# Backup user menu bar configuration
backup_user_menubar_config() {
    local user="$1"
    local timestamp
    timestamp=$(date '+%Y%m%d_%H%M%S')
    
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    local backup_file="$BACKUP_DIR/menubar_${user}_${timestamp}.plist"
    
    if [[ -f "$plist_path" ]]; then
        cp "$plist_path" "$backup_file" 2>/dev/null
        log_action "Backed up menu bar config for $user: $backup_file"
        echo "$backup_file"
    fi
}

# Custom menu bar configuration
configure_custom_menubar() {
    local items_string="$1"
    local target_user="$2"
    
    log_action "Applying custom menu bar configuration: $items_string"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Parse items
    IFS=',' read -ra ITEMS <<< "$items_string"
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Backup and clear
        backup_user_menubar_config "$user"
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Add custom items
        local index=0
        for item in "${ITEMS[@]}"; do
            # Remove whitespace
            item=$(echo "$item" | sed 's/^[ \t]*//;s/[ \t]*$//')
            
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                ((index++))
            fi
        done
        
        # Apply changes
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Custom configuration applied to user: $user"
    done
}

# Generate menu bar audit report
generate_menubar_audit() {
    log_action "Generating menu bar audit report"
    
    local report_file="$REPORTS_DIR/menubar_audit_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$report_file" << EOF
{
    "audit_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)",
        "os_version": "$(sw_vers -productVersion)",
        "generator": "Roundfleet Menu Bar Manager"
    },
    "user_configurations": [
EOF

    local first=true
    local total_users=0
    
    # Audit each user
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        total_users=$((total_users + 1))
        
        if [[ "$first" == true ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        
        local current_config
        current_config=$(get_current_menubar_config "$user")
        
        local last_login
        last_login=$(last -1 "$user" | head -1 | awk '{print $4, $5, $6, $7}' || echo 'Never')
        
        cat >> "$report_file" << EOF
        {
            "username": "$user",
            "current_menu_items": $current_config,
            "item_count": $(echo "$current_config" | jq 'length'),
            "last_login": "$last_login",
            "config_file_exists": $([ -f "/Users/$user/Library/Preferences/com.apple.systemuiserver.plist" ] && echo "true" || echo "false")
        }
EOF
        
        log_action "Audited user: $user"
    done
    
    cat >> "$report_file" << EOF
    ],
    "summary": {
        "total_users": $total_users,
        "available_menu_items": $(echo "${!MENU_EXTRAS[@]}" | tr ' ' '\n' | jq -R . | jq -s .),
        "available_profiles": $(echo "${!MENU_PROFILES[@]}" | tr ' ' '\n' | jq -R . | jq -s .)
    }
}
EOF

    log_action "✅ Menu bar audit completed: $report_file"
    echo "$report_file"
}

# Restore menu bar configuration from backup
restore_menubar_config() {
    local backup_file="$1"
    local target_user="$2"
    
    if [[ ! -f "$backup_file" ]]; then
        log_action "❌ Backup file not found: $backup_file"
        return 1
    fi
    
    log_action "Restoring menu bar configuration from: $backup_file"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Extract username from backup filename
        local extracted_user
        extracted_user=$(basename "$backup_file" | sed 's/menubar_\(.*\)_[0-9]*_[0-9]*.plist/\1/')
        if [[ -n "$extracted_user" ]]; then
            users=("$extracted_user")
        fi
    fi
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Create current backup before restore
        backup_user_menubar_config "$user"
        
        # Restore configuration
        if cp "$backup_file" "$plist_path" 2>/dev/null; then
            chown "$user:staff" "$plist_path" 2>/dev/null
            
            # Apply changes
            run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
            run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
            
            log_action "✅ Configuration restored for user: $user"
        else
            log_action "❌ Failed to restore configuration for user: $user"
            return 1
        fi
    done
    
    return 0
}

# Monitor menu bar changes
monitor_menubar_changes() {
    local duration="${1:-3600}"  # 1 hour default
    local check_interval="${2:-60}"  # 1 minute default
    
    log_action "Starting menu bar monitoring for ${duration} seconds"
    
    local monitoring_report="$REPORTS_DIR/menubar_monitoring_$(date '+%Y%m%d_%H%M%S').json"
    local baseline_file="/tmp/menubar_baseline.json"
    
    # Create baseline
    generate_menubar_audit > "$baseline_file"
    
    cat > "$monitoring_report" << EOF
{
    "monitoring_metadata": {
        "start_time": "$(date -Iseconds)",
        "duration_seconds": $duration,
        "check_interval_seconds": $check_interval,
        "hostname": "$(hostname)"
    },
    "changes_detected": [
EOF

    local start_time end_time
    start_time=$(date +%s)
    end_time=$((start_time + duration))
    
    local first=true
    while [[ $(date +%s) -lt $end_time ]]; do
        sleep "$check_interval"
        
        # Check for changes
        local current_state="/tmp/menubar_current.json"
        generate_menubar_audit > "$current_state"
        
        if ! diff "$baseline_file" "$current_state" >/dev/null 2>&1; then
            if [[ "$first" == true ]]; then
                first=false
            else
                echo "," >> "$monitoring_report"
            fi
            
            cat >> "$monitoring_report" << EOF
        {
            "timestamp": "$(date -Iseconds)",
            "change_type": "menu_bar_configuration_change",
            "details": "Changes detected in menu bar configuration"
        }
EOF
            
            log_action "⚠️  Menu bar configuration changes detected"
            cp "$current_state" "$baseline_file"
        fi
        
        rm -f "$current_state"
    done
    
    cat >> "$monitoring_report" << EOF
    ],
    "end_time": "$(date -Iseconds)"
}
EOF

    log_action "✅ Menu bar monitoring completed: $monitoring_report"
    rm -f "$baseline_file"
    echo "$monitoring_report"
}

# Main execution function
main() {
    local action="${1:-audit}"
    local parameter="$2"
    local additional_param="$3"
    
    log_action "=== Roundfleet Menu Bar Management Started ==="
    log_action "Action: $action"
    log_action "Parameter: ${parameter:-N/A}"
    
    setup_directories
    
    case "$action" in
        "profile")
            if [[ -z "$parameter" ]]; then
                echo "Available menu bar profiles:"
                for profile in "${!MENU_PROFILES[@]}"; do
                    echo "  - $profile: ${MENU_PROFILES[$profile]}"
                done
                echo ""
                echo "Usage: $0 profile <profile_name> [username]"
                exit 1
            fi
            apply_menubar_profile "$parameter" "$additional_param"
            ;;
        "custom")
            if [[ -z "$parameter" ]]; then
                echo "Available menu items:"
                for item in "${!MENU_EXTRAS[@]}"; do
                    echo "  - $item"
                done
                echo ""
                echo "Usage: $0 custom <item1,item2,item3> [username]"
                echo "Example: $0 custom clock,battery,wifi,vpn john.doe"
                exit 1
            fi
            configure_custom_menubar "$parameter" "$additional_param"
            ;;
        "audit")
            generate_menubar_audit
            ;;
        "monitor")
            monitor_menubar_changes "$parameter" "$additional_param"
            ;;
        "restore")
            if [[ -z "$parameter" ]]; then
                echo "Usage: $0 restore <backup_file> [username]"
                echo "Available backups:"
                ls -la "$BACKUP_DIR"/*.plist 2>/dev/null || echo "No backups found"
                exit 1
            fi
            restore_menubar_config "$parameter" "$additional_param"
            ;;
        "hide-vpn")
            local user
            if user=$(get_current_user); then
                hide_vpn_icon
            else
                echo "❌ No active user session"
                exit 1
            fi
            ;;
        "show-vpn")
            local user
            if user=$(get_current_user); then
                show_vpn_icon
            else
                echo "❌ No active user session"
                exit 1
            fi
            ;;
        *)
            echo "Usage: $0 {profile|custom|audit|monitor|restore|hide-vpn|show-vpn}"
            echo "  profile     - Apply predefined menu bar profile"
            echo "  custom      - Apply custom menu bar configuration"
            echo "  audit       - Generate menu bar audit report"
            echo "  monitor     - Monitor menu bar changes over time"
            echo "  restore     - Restore from backup"
            echo "  hide-vpn    - Hide VPN icon from menu bar"
            echo "  show-vpn    - Show VPN icon in menu bar"
            exit 1
            ;;
    esac
    
    log_action "=== Menu bar management completed ==="
}

# Execute main function
main "$@"

Menu Bar Profile Examples

Corporate Profile Setup

#!/bin/bash

# Apply corporate menu bar profile across all devices
deploy_corporate_profile() {
    echo "=== Corporate Menu Bar Deployment ==="
    
    # Corporate profile: clock, battery, wifi, vpn, timemachine
    local corporate_items="clock,battery,wifi,vpn,timemachine"
    
    # Get all users
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        echo "Configuring corporate profile for: $user"
        
        # Apply configuration
        configure_custom_menubar "$corporate_items" "$user"
        
        # Verify application
        sleep 2
        local current_config
        current_config=$(get_current_menubar_config "$user")
        echo "Applied configuration: $current_config"
    done
    
    echo "✅ Corporate profile deployed to all users"
}

Kiosk Mode Configuration

#!/bin/bash

# Minimal menu bar for kiosk environments
setup_kiosk_menubar() {
    echo "=== Kiosk Menu Bar Setup ==="
    
    # Minimal items: clock and battery only
    local kiosk_items="clock,battery"
    
    local target_user="$1"
    if [[ -z "$target_user" ]]; then
        echo "Usage: setup_kiosk_menubar <username>"
        return 1
    fi
    
    configure_custom_menubar "$kiosk_items" "$target_user"
    
    echo "✅ Kiosk menu bar configured for: $target_user"
}

Advanced Menu Bar Features

Dynamic Profile Switching

#!/bin/bash

# Switch between different profiles based on conditions
smart_profile_switching() {
    local user="$1"
    
    echo "=== Smart Profile Switching ==="
    
    # Detect environment
    if pgrep -f "VPN" >/dev/null; then
        echo "VPN detected - applying corporate profile"
        apply_menubar_profile "corporate" "$user"
    elif [[ $(pmset -g batt | grep -c "Battery") -gt 0 ]]; then
        echo "Battery power detected - applying minimal profile"
        apply_menubar_profile "minimal" "$user"
    else
        echo "Standard environment - applying full profile"
        apply_menubar_profile "full" "$user"
    fi
}

Menu Bar Health Check

#!/bin/bash

# Verify menu bar configuration integrity
menubar_health_check() {
    echo "=== Menu Bar Health Check ==="
    
    local issues_found=0
    
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        if [[ ! -f "$plist_path" ]]; then
            echo "⚠️  Missing configuration file for user: $user"
            issues_found=$((issues_found + 1))
            continue
        fi
        
        # Check if SystemUIServer is running
        if ! pgrep -u "$(id -u "$user")" SystemUIServer >/dev/null; then
            echo "⚠️  SystemUIServer not running for user: $user"
            issues_found=$((issues_found + 1))
        fi
        
        # Validate plist format
        if ! plutil -lint "$plist_path" >/dev/null 2>&1; then
            echo "❌ Corrupted plist file for user: $user"
            issues_found=$((issues_found + 1))
        fi
    done
    
    if [[ $issues_found -eq 0 ]]; then
        echo "✅ All menu bar configurations are healthy"
    else
        echo "⚠️  Found $issues_found issues requiring attention"
    fi
    
    return $issues_found
}

Best Practices

🎯 User Experience Optimization

  • Consistent branding across all devices with standardized menu bar layouts
  • Profile-based configurations for different user roles and environments
  • Minimal kiosk setups for public or restricted-use devices
  • Dynamic switching based on power state or network conditions

🔧 Enterprise Management

  • Centralized deployment of menu bar configurations across device fleets
  • Backup and restore capabilities for configuration management
  • Audit reporting for compliance and standardization verification
  • Change monitoring with automated detection and alerting

🔐 Security Considerations

  • Remove sensitive indicators from public-facing devices
  • Hide VPN status in environments where network information should be private
  • Standardize corporate displays to prevent information leakage
  • Monitor unauthorized changes to menu bar configurations

📊 Monitoring and Maintenance

  • Regular health checks to ensure configuration integrity
  • Automated profile enforcement to maintain consistency
  • Change detection with rollback capabilities
  • User experience feedback collection and optimization

Important Notes

  • macOS 12+ required for optimal compatibility with modern menu extras
  • User session active required for menu bar modifications
  • System restart may be needed for some changes to take full effect
  • Test thoroughly before deploying to production environments
  • Backup configurations before making changes to allow easy rollback

Manage System Settings Panels on macOS

Control which System Settings panels users can access on macOS Ventura and later versions. This tutorial shows how to disable or hide specific preference panes to maintain security and prevent unwanted configuration changes across your Roundfleet.

Understanding System Settings vs System Preferences

macOS Ventura (13.0+) replaced "System Preferences" with "System Settings". The management approach differs between versions:

  • macOS 13.0+: Use DisabledSystemSettings and bundle identifiers ending in .extension
  • macOS 12.x and earlier: Use DisabledPreferencePanes with different bundle identifiers

Disable System Settings Panels

Basic Disable Script

#!/bin/bash

# Disable specific System Settings panel
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "com.apple.Battery-Settings.extension"

echo "System Settings panel disabled successfully"

Disable Multiple Panels

#!/bin/bash

# Disable multiple System Settings panels
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings" \
    "com.apple.Network-Settings.extension" \
    "com.apple.Battery-Settings.extension"

echo "Multiple System Settings panels disabled"

System Settings Bundle Identifiers

Panel NameBundle Identifier
Accessibilitycom.apple.Accessibility-Settings.extension
AirDrop & Handoffcom.apple.AirDrop-Handoff-Settings.extension
Apple IDcom.apple.systempreferences.AppleIDSettings
Batterycom.apple.Battery-Settings.extension
Bluetoothcom.apple.BluetoothSettings
Control Centercom.apple.ControlCenter-Settings.extension
Date & Timecom.apple.Date-Time-Settings.extension
Desktop & Dockcom.apple.Desktop-Settings.extension
Displayscom.apple.Displays-Settings.extension
Extensionscom.apple.ExtensionsPreferences
Focuscom.apple.Focus-Settings.extension
Game Centercom.apple.Game-Center-Settings.extension
Internet Accountscom.apple.Internet-Accounts-Settings.extension
Keyboardcom.apple.Keyboard-Settings.extension
Language & Regioncom.apple.Localization-Settings.extension
Lock Screencom.apple.Lock-Screen-Settings.extension
Login Itemscom.apple.LoginItems-Settings.extension
Networkcom.apple.Network-Settings.extension
Notificationscom.apple.Notifications-Settings.extension
Passwordscom.apple.Passwords-Settings.extension
Printers & Scannerscom.apple.Print-Scan-Settings.extension
Screen Timecom.apple.Screen-Time-Settings.extension
Screen Savercom.apple.ScreenSaver-Settings.extension
Sharingcom.apple.Sharing-Settings.extension
Siri & Spotlightcom.apple.Siri-Settings.extension
Software Updatecom.apple.Software-Update-Settings.extension
Soundcom.apple.Sound-Settings.extension
Startup Diskcom.apple.Startup-Disk-Settings.extension
Storagecom.apple.settings.Storage
Time Machinecom.apple.Time-Machine-Settings.extension
Touch ID & Passwordcom.apple.Touch-ID-Settings.extension
Trackpadcom.apple.Trackpad-Settings.extension
Transfer or Resetcom.apple.Transfer-Reset-Settings.extension
Users & Groupscom.apple.Users-Groups-Settings.extension
Wallet & Apple Paycom.apple.WalletSettingsExtension
Wallpapercom.apple.Wallpaper-Settings.extension
Wi-Ficom.apple.wifi-settings-extension

Open System Settings Panels Remotely

Open Specific Panel

#!/bin/bash

# Open Network settings panel
open "x-apple.systempreferences:com.apple.Network-Settings.extension"

echo "Network settings panel opened"

Conditional Panel Opening

#!/bin/bash

PANEL_ID="com.apple.Battery-Settings.extension"

# Check if panel is not disabled before opening
if ! defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "$PANEL_ID"; then
    open "x-apple.systempreferences:$PANEL_ID"
    echo "Battery settings panel opened"
else
    echo "Battery settings panel is disabled"
fi

Re-enable Disabled Panels

Re-enable All Panels

#!/bin/bash

# Remove all disabled System Settings restrictions
defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

echo "All System Settings panels re-enabled"

Re-enable Specific Panels

#!/bin/bash

# Get current disabled panels
CURRENT_DISABLED=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null)

# Remove specific panel from disabled list (requires custom logic)
# This example shows the concept - implement based on your needs
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings"
    # Add other panels you want to keep disabled

echo "Specific System Settings panels re-enabled"

Enterprise Management Script

#!/bin/bash

# Enterprise System Settings Management
# Restricts access to sensitive configuration panels

RESTRICTED_PANELS=(
    "com.apple.Network-Settings.extension"
    "com.apple.BluetoothSettings"
    "com.apple.Security-Privacy-Settings.extension"
    "com.apple.Software-Update-Settings.extension"
    "com.apple.Users-Groups-Settings.extension"
)

# Apply restrictions
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "${RESTRICTED_PANELS[@]}"

# Verify restrictions
echo "Disabled System Settings panels:"
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null || echo "No panels currently disabled"

# Log the action
logger "Roundfleet: System Settings panels restricted on $(date)"

Troubleshooting

Check Current Restrictions

# View currently disabled panels
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

# Check if specific panel is disabled
if defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "com.apple.Battery-Settings.extension"; then
    echo "Battery panel is disabled"
else
    echo "Battery panel is accessible"
fi

Clear All Restrictions

# Emergency reset - re-enable all panels
sudo defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings
sudo killall cfprefsd

Common Use Cases

ScenarioRecommended Panels to Disable
Shared WorkstationsUsers & Groups, Software Update, Network
BYOD DevicesApple ID, Transfer or Reset, Users & Groups
Kiosk ModeAll except essential panels for operation
Educational LabsNetwork, Software Update, Touch ID & Password
Corporate SecuritySoftware Update, Transfer or Reset, Sharing

Important Notes

  • macOS Compatibility: These scripts work only on macOS 13.0 (Ventura) and later
  • User Experience: Disabled panels appear grayed out but remain visible
  • System Restart: Changes take effect immediately without restart
  • Persistence: Settings persist across user sessions and system reboots

For devices running macOS 12.x and earlier, use the legacy System Preferences management approach with different bundle identifiers.

Manage Running Processes on macOS

Monitor and control running processes on your Roundfleet devices using command-line tools. This tutorial covers CPU monitoring, memory analysis, process listing, and process termination for effective system management.

Understanding macOS Process Management

macOS provides several command-line tools for process management:

  • top - Real-time display of running processes and system usage
  • ps - Snapshot of current processes
  • kill - Terminate processes by PID
  • Activity Monitor - GUI equivalent for visual monitoring

Show CPU Utilization

Basic CPU Usage

#!/bin/bash

# Display current CPU utilization
top -l 1 -s 0 | grep "CPU usage"

echo "CPU utilization retrieved successfully"

Detailed CPU Analysis

#!/bin/bash

# Get comprehensive CPU information
echo "=== CPU Utilization Analysis ==="
echo "Current CPU Usage:"
top -l 1 -s 0 | grep "CPU usage"

echo -e "\nTop CPU-consuming processes:"
top -l 1 -s 0 | head -20 | tail -10

echo -e "\nLoad average:"
uptime

Show Memory Status

Basic Memory Information

#!/bin/bash

# Display memory utilization
top -l 1 -s 0 | grep PhysMem

echo "Memory status retrieved successfully"

Comprehensive Memory Analysis

#!/bin/bash

# Detailed memory report
echo "=== Memory Status Analysis ==="
echo "Physical Memory Usage:"
top -l 1 -s 0 | grep PhysMem

echo -e "\nVirtual Memory Statistics:"
vm_stat

echo -e "\nMemory pressure:"
memory_pressure

List Running Processes

View All Processes

#!/bin/bash

# List all running processes
ps aux

echo "Process list generated successfully"

Limited Process List

#!/bin/bash

# Show top 10 processes
echo "Top 10 running processes:"
ps aux | head -11

# Show specific number of processes (replace 15 with desired count)
echo -e "\nTop 15 processes:"
ps aux | head -16

Filtered Process Views

#!/bin/bash

# Show only user processes
echo "User processes:"
ps aux | grep -v "^root"

echo -e "\nSystem processes:"
ps aux | grep "^root" | head -10

echo -e "\nProcesses using most CPU:"
ps aux --sort=-%cpu | head -10

echo -e "\nProcesses using most memory:"
ps aux --sort=-%mem | head -10

Process Termination

Kill Process by PID

#!/bin/bash

# Kill specific process (replace PID with actual process ID)
PID="1234"

if kill -9 "$PID" 2>/dev/null; then
    echo "Process $PID terminated successfully"
else
    echo "Failed to terminate process $PID or process not found"
fi

Kill Process by Name

#!/bin/bash

# Kill process by application name
APP_NAME="Safari"

if pkill -f "$APP_NAME"; then
    echo "$APP_NAME processes terminated successfully"
else
    echo "No $APP_NAME processes found or termination failed"
fi

Safe Process Termination

#!/bin/bash

# Gracefully terminate process with confirmation
terminate_process() {
    local pid="$1"
    local process_name
    
    # Get process name
    process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
    
    if [[ -z "$process_name" ]]; then
        echo "Process $pid not found"
        return 1
    fi
    
    echo "Found process: $process_name (PID: $pid)"
    
    # Try graceful termination first
    if kill -TERM "$pid" 2>/dev/null; then
        echo "Sent termination signal to $process_name"
        sleep 3
        
        # Check if process still exists
        if kill -0 "$pid" 2>/dev/null; then
            echo "Process still running, forcing termination..."
            kill -9 "$pid" 2>/dev/null
        fi
        
        echo "Process $process_name terminated"
        return 0
    else
        echo "Failed to terminate process $process_name"
        return 1
    fi
}

# Usage example (replace with actual PID)
# terminate_process 1234

Enterprise Process Management Script

#!/bin/bash

# Roundfleet Process Management Tool
# Monitor and manage processes across fleet devices

# Configuration
LOG_FILE="/var/log/roundfleet_processes.log"
ALERT_CPU_THRESHOLD=80
ALERT_MEMORY_THRESHOLD=80

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Get system statistics
get_system_stats() {
    echo "=== System Statistics ==="
    
    # CPU usage
    local cpu_info
    cpu_info=$(top -l 1 -s 0 | grep "CPU usage")
    echo "CPU: $cpu_info"
    
    # Memory usage
    local mem_info
    mem_info=$(top -l 1 -s 0 | grep PhysMem)
    echo "Memory: $mem_info"
    
    # Load average
    echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
    
    # Top processes
    echo -e "\nTop 5 CPU consumers:"
    ps aux --sort=-%cpu | head -6 | tail -5
    
    echo -e "\nTop 5 Memory consumers:"
    ps aux --sort=-%mem | head -6 | tail -5
}

# Check for problematic processes
check_system_health() {
    echo "=== System Health Check ==="
    
    # Check high CPU usage processes
    local high_cpu_procs
    high_cpu_procs=$(ps aux | awk -v threshold="$ALERT_CPU_THRESHOLD" '$3 > threshold {print $2, $11, $3"%"}')
    
    if [[ -n "$high_cpu_procs" ]]; then
        echo "⚠️  High CPU usage processes:"
        echo "$high_cpu_procs"
        log_action "High CPU alert: $high_cpu_procs"
    fi
    
    # Check high memory usage processes
    local high_mem_procs
    high_mem_procs=$(ps aux | awk -v threshold="$ALERT_MEMORY_THRESHOLD" '$4 > threshold {print $2, $11, $4"%"}')
    
    if [[ -n "$high_mem_procs" ]]; then
        echo "⚠️  High memory usage processes:"
        echo "$high_mem_procs"
        log_action "High memory alert: $high_mem_procs"
    fi
}

# Kill runaway processes
kill_runaway_processes() {
    echo "=== Runaway Process Detection ==="
    
    # Find processes using excessive CPU (>90% for >5 minutes)
    local runaway_pids
    runaway_pids=$(ps aux | awk '$3 > 90 {print $2}')
    
    for pid in $runaway_pids; do
        local process_name
        process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
        
        if [[ -n "$process_name" ]]; then
            echo "Found runaway process: $process_name (PID: $pid)"
            
            # Skip critical system processes
            if [[ "$process_name" =~ ^(kernel|launchd|WindowServer)$ ]]; then
                echo "Skipping critical system process: $process_name"
                continue
            fi
            
            log_action "Terminating runaway process: $process_name (PID: $pid)"
            kill -TERM "$pid"
        fi
    done
}

# Main monitoring function
main() {
    log_action "=== Roundfleet Process Monitoring Started ==="
    
    get_system_stats
    echo ""
    check_system_health
    echo ""
    
    # Optionally kill runaway processes (uncomment to enable)
    # kill_runaway_processes
    
    log_action "=== Process monitoring completed ==="
}

# Execute main function
main "$@"

Process Information Details

When using ps aux, each column provides specific information:

ColumnDescription
USERUser running the process (system or user process)
PIDProcess ID (unique identifier)
%CPUCPU usage percentage
%MEMMemory usage percentage
VSZVirtual memory size in KB
RSSPhysical memory usage in KB
TTTerminal associated with process
STATProcess status (R=running, S=sleeping, Z=zombie)
STARTEDProcess start date/time
TIMECPU time consumed
COMMANDCommand used to start the process

Common Process Management Tasks

Find Process by Name

# Find Safari processes
ps aux | grep -i safari

# Find all processes containing "mail"
ps aux | grep -i mail | grep -v grep

Monitor Process in Real-time

# Watch specific process
watch -n 1 'ps aux | grep -i safari'

# Monitor system resources continuously
top -s 1 -n 10

Generate Process Report

#!/bin/bash

# Create comprehensive process report
REPORT_FILE="process_report_$(date +%Y%m%d_%H%M%S).txt"

{
    echo "Roundfleet Process Report"
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo "=========================="
    echo ""
    
    echo "System Overview:"
    top -l 1 -s 0 | grep -E "(CPU usage|PhysMem)"
    echo ""
    
    echo "Top 20 Processes:"
    ps aux | head -21
    echo ""
    
    echo "Process Count by User:"
    ps aux | awk '{print $1}' | sort | uniq -c | sort -nr
    
} > "$REPORT_FILE"

echo "Process report saved to: $REPORT_FILE"

Important Notes

  • Process IDs (PIDs) change when processes restart
  • System processes require admin privileges to terminate
  • Force kill (kill -9) should be used as last resort
  • Monitor resource usage before terminating processes
  • Test scripts on individual devices before fleet deployment

Manage FileVault Encryption on macOS

FileVault provides full-disk encryption for macOS devices, protecting sensitive data even if the device is lost or stolen. This tutorial shows how to automate FileVault management across your Roundfleet using command-line scripts.

Understanding FileVault

FileVault encrypts the entire startup disk using XTS-AES-128 encryption with a 256-bit key. Key benefits include:

  • Data Protection - Encrypts all data on the startup disk
  • Compliance - Meets enterprise security requirements
  • Performance - Hardware-accelerated encryption on modern Macs
  • Recovery - Multiple recovery options available

Basic FileVault Commands

Check FileVault Status

#!/bin/bash

# Check current FileVault status
fdesetup status

# Get detailed encryption information
diskutil apfs listCryptoUsers /

Enable FileVault

#!/bin/bash

# Basic FileVault enable command
sudo fdesetup enable --user "username" --password "password"

# Enable with specific keychain
sudo fdesetup enable --user "username" --password "password" --keychain /Library/Keychains/System.keychain

Disable FileVault

#!/bin/bash

# Basic FileVault disable command
sudo fdesetup disable --user "username" --password "password"

Enterprise FileVault Management Script

Complete script for managing FileVault across your Roundfleet:

#!/bin/bash

# FileVault Management Script for Roundfleet
# Compatible with macOS 10.14+

# Configuration
LOG_FILE="/var/log/filevault_management.log"
KEYCHAIN_PATH="/Library/Keychains/System.keychain"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Function to get current user
get_current_user() {
    stat -f "%Su" /dev/console
}

# Function to check if user has secure token
check_secure_token() {
    local username="$1"
    
    if sysadminctl -secureTokenStatus "$username" 2>/dev/null | grep -q "ENABLED"; then
        return 0
    else
        return 1
    fi
}

# Function to check FileVault status
check_filevault_status() {
    local status
    status=$(fdesetup status)
    
    if echo "$status" | grep -q "FileVault is On"; then
        echo "enabled"
    elif echo "$status" | grep -q "FileVault is Off"; then
        echo "disabled"
    elif echo "$status" | grep -q "Encryption in progress"; then
        echo "encrypting"
    elif echo "$status" | grep -q "Decryption in progress"; then
        echo "decrypting"
    else
        echo "unknown"
    fi
}

# Function to get encryption progress
get_encryption_progress() {
    fdesetup status | grep -o '[0-9]\+%' | head -1
}

# Function to validate user credentials
validate_user_credentials() {
    local username="$1"
    local password="$2"
    
    # Check if user exists
    if ! id "$username" &>/dev/null; then
        log_message "✗ User does not exist: $username"
        return 1
    fi
    
    # Check if user has admin privileges
    if ! dsmemberutil checkmembership -U "$username" -G admin &>/dev/null; then
        log_message "✗ User is not an administrator: $username"
        return 1
    fi
    
    # Check if user has secure token
    if ! check_secure_token "$username"; then
        log_message "✗ User does not have secure token: $username"
        return 1
    fi
    
    # Verify password (basic check)
    if [[ -z "$password" ]]; then
        log_message "✗ Password cannot be empty for user: $username"
        return 1
    fi
    
    log_message "✓ User credentials validated: $username"
    return 0
}

# Function to enable FileVault
enable_filevault() {
    local username="$1"
    local password="$2"
    local force_enable="$3"
    
    log_message "Starting FileVault enablement for user: $username"
    
    # Check current status
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "enabled")
            log_message "! FileVault is already enabled"
            if [[ "$force_enable" != "true" ]]; then
                return 0
            fi
            ;;
        "encrypting")
            log_message "! FileVault encryption is already in progress"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Encryption progress: ${progress:-Unknown}"
            return 0
            ;;
        "decrypting")
            log_message "✗ Cannot enable FileVault while decryption is in progress"
            return 1
            ;;
    esac
    
    # Validate user credentials
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Enable FileVault
    log_message "Enabling FileVault..."
    
    if fdesetup enable -user "$username" -password "$password" -keychain "$KEYCHAIN_PATH" 2>/dev/null; then
        log_message "✓ FileVault enable command executed successfully"
        
        # Wait a moment and check status
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "enabled")
                log_message "✓ FileVault is now enabled"
                ;;
            "encrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ FileVault encryption started (${progress:-0%})"
                ;;
            *)
                log_message "! FileVault status unclear: $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Failed to enable FileVault"
        return 1
    fi
}

# Function to disable FileVault
disable_filevault() {
    local username="$1"
    local password="$2"
    local force_disable="$3"
    
    log_message "Starting FileVault disablement for user: $username"
    
    # Check current status
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "disabled")
            log_message "! FileVault is already disabled"
            if [[ "$force_disable" != "true" ]]; then
                return 0
            fi
            ;;
        "decrypting")
            log_message "! FileVault decryption is already in progress"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Decryption progress: ${progress:-Unknown}"
            return 0
            ;;
        "encrypting")
            log_message "✗ Cannot disable FileVault while encryption is in progress"
            return 1
            ;;
    esac
    
    # Validate user credentials
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Disable FileVault
    log_message "Disabling FileVault..."
    
    if fdesetup disable -user "$username" -password "$password" 2>/dev/null; then
        log_message "✓ FileVault disable command executed successfully"
        
        # Wait a moment and check status
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "disabled")
                log_message "✓ FileVault is now disabled"
                ;;
            "decrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ FileVault decryption started (${progress:-0%})"
                ;;
            *)
                log_message "! FileVault status unclear: $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Failed to disable FileVault"
        return 1
    fi
}

# Function to get system information
get_system_info() {
    log_message "=== System Information ==="
    log_message "Hostname: $(hostname)"
    log_message "macOS Version: $(sw_vers -productVersion)"
    log_message "Current User: $(get_current_user)"
    log_message "FileVault Status: $(check_filevault_status)"
    
    # Get FileVault users
    local fv_users
    fv_users=$(fdesetup list 2>/dev/null)
    if [[ -n "$fv_users" ]]; then
        log_message "FileVault Enabled Users:"
        echo "$fv_users" | while read -r line; do
            log_message "  $line"
        done
    fi
}

# Function to display usage
usage() {
    echo "Usage: $0 {enable|disable|status} [options]"
    echo ""
    echo "Commands:"
    echo "  enable    Enable FileVault"
    echo "  disable   Disable FileVault"
    echo "  status    Check FileVault status"
    echo ""
    echo "Options:"
    echo "  -u, --user USERNAME      Specify username"
    echo "  -p, --password PASSWORD  Specify password"
    echo "  -f, --force             Force operation even if already in desired state"
    echo "  -h, --help              Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0 enable -u admin -p password123"
    echo "  $0 disable -u admin -p password123 -f"
    echo "  $0 status"
}

# Main function
main() {
    local command="$1"
    local username=""
    local password=""
    local force="false"
    
    # Parse arguments
    shift
    while [[ $# -gt 0 ]]; do
        case $1 in
            -u|--user)
                username="$2"
                shift 2
                ;;
            -p|--password)
                password="$2"
                shift 2
                ;;
            -f|--force)
                force="true"
                shift
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done
    
    # Execute command
    case "$command" in
        "enable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Error: Username and password required for enable command"
                usage
                exit 1
            fi
            
            log_message "=== Starting FileVault Enable Operation ==="
            get_system_info
            
            if enable_filevault "$username" "$password" "$force"; then
                log_message "=== FileVault Enable Operation Completed Successfully ==="
                exit 0
            else
                log_message "=== FileVault Enable Operation Failed ==="
                exit 1
            fi
            ;;
        "disable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Error: Username and password required for disable command"
                usage
                exit 1
            fi
            
            log_message "=== Starting FileVault Disable Operation ==="
            get_system_info
            
            if disable_filevault "$username" "$password" "$force"; then
                log_message "=== FileVault Disable Operation Completed Successfully ==="
                exit 0
            else
                log_message "=== FileVault Disable Operation Failed ==="
                exit 1
            fi
            ;;
        "status")
            get_system_info
            exit 0
            ;;
        *)
            echo "Error: Invalid command: $command"
            usage
            exit 1
            ;;
    esac
}

# Execute main function
main "$@"

Quick FileVault Scripts

Simple Enable Script

#!/bin/bash

USERNAME="admin"
PASSWORD="your_password_here"

if fdesetup enable -user "$USERNAME" -password "$PASSWORD"; then
    echo "FileVault enabled successfully"
else
    echo "Failed to enable FileVault"
    exit 1
fi

Simple Status Check

#!/bin/bash

STATUS=$(fdesetup status)
echo "FileVault Status: $STATUS"

if echo "$STATUS" | grep -q "FileVault is On"; then
    echo "✓ FileVault is enabled"
    exit 0
elif echo "$STATUS" | grep -q "FileVault is Off"; then
    echo "✗ FileVault is disabled"
    exit 1
else
    echo "! FileVault status unclear"
    exit 2
fi

Recovery Key Management

Generate Personal Recovery Key

#!/bin/bash

# Enable FileVault with personal recovery key
sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -outputplist > /tmp/filevault_key.plist

# Extract recovery key
RECOVERY_KEY=$(grep -A1 "RecoveryKey" /tmp/filevault_key.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>.*/\1/')

echo "Recovery Key: $RECOVERY_KEY"

# Securely store recovery key
echo "$RECOVERY_KEY" | sudo tee /var/root/filevault_recovery_key.txt
sudo chmod 600 /var/root/filevault_recovery_key.txt

# Clean up
rm -f /tmp/filevault_key.plist

Enable Institutional Recovery Key

#!/bin/bash

# Create institutional recovery key
CERT_PATH="/path/to/institutional_certificate.cer"

if [[ -f "$CERT_PATH" ]]; then
    sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -certificate "$CERT_PATH"
    echo "FileVault enabled with institutional recovery key"
else
    echo "Institutional certificate not found: $CERT_PATH"
    exit 1
fi

Troubleshooting Common Issues

Fix Secure Token Issues

#!/bin/bash

USERNAME="admin"

# Grant secure token to user
sudo sysadminctl -secureTokenOn "$USERNAME" -password -

# Verify secure token
if sysadminctl -secureTokenStatus "$USERNAME" | grep -q "ENABLED"; then
    echo "✓ Secure token enabled for $USERNAME"
else
    echo "✗ Failed to enable secure token for $USERNAME"
fi

Handle Blank Password Error

#!/bin/bash

USERNAME="admin"

# Check if user has a password set
if dscl . -read "/Users/$USERNAME" AuthenticationAuthority | grep -q "No such key"; then
    echo "User $USERNAME has no password set"
    echo "Setting password..."
    sudo dscl . -passwd "/Users/$USERNAME" "" "new_password_here"
fi

Monitoring and Reporting

FileVault Status Report

#!/bin/bash

# Generate FileVault status report
REPORT_FILE="/tmp/filevault_report.txt"

{
    echo "=== FileVault Status Report ==="
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo ""
    
    echo "=== FileVault Status ==="
    fdesetup status
    echo ""
    
    echo "=== Enabled Users ==="
    fdesetup list
    echo ""
    
    echo "=== Secure Token Status ==="
    for user in $(dscl . -list /Users | grep -v '^_'); do
        if [[ "$user" != "daemon" ]] && [[ "$user" != "nobody" ]]; then
            token_status=$(sysadminctl -secureTokenStatus "$user" 2>/dev/null | grep -o "ENABLED\|DISABLED")
            echo "User: $user - Token: ${token_status:-UNKNOWN}"
        fi
    done
    
} > "$REPORT_FILE"

echo "Report generated: $REPORT_FILE"

Common Error Solutions

ErrorCauseSolution
"Blank password"User has no passwordSet password with dscl . -passwd
"Master keychain found"Keychain ambiguityAdd -keychain parameter
"Secure token required"User lacks secure tokenGrant token with sysadminctl
"Already encrypted"FileVault already onUse -force or check status first
"Encryption in progress"Concurrent operationWait for completion

Security Best Practices

  • Use strong passwords for FileVault-enabled accounts
  • Store recovery keys securely in enterprise key management
  • Test scripts on isolated devices before fleet deployment
  • Monitor encryption progress to ensure completion
  • Backup recovery keys before making changes
  • Validate user permissions before attempting operations

Performance Considerations

  • Initial encryption can take several hours
  • System performance may be impacted during encryption
  • Schedule operations during maintenance windows
  • Monitor disk space (encryption requires free space)
  • Consider SSD vs HDD performance differences

Important Notes

  • FileVault requires admin privileges and secure tokens
  • Recovery keys are essential for data recovery
  • Encryption/decryption cannot be interrupted safely
  • Test all scripts thoroughly before production use
  • Always have a backup recovery plan

macOS Update Management

Implement enterprise-grade macOS update management across your Roundfleet deployment with automated patch deployment, compliance monitoring, staged rollouts, and comprehensive update policies. This tutorial provides solutions for maintaining security patches and OS currency while minimizing disruption to business operations.

Understanding macOS Update Management

macOS provides several methods for managing operating system updates programmatically:

  • Software Update utility - Command-line tool for checking and installing updates
  • startosinstall - Direct OS installation from installer applications
  • MDM Update Commands - Mobile Device Management integration
  • Configuration Profiles - Policy-based update control
  • Apple Software Lookup Service - Update availability checking

Basic Update Operations

List Available Updates

#!/bin/bash

# List all available OS versions for installation
softwareupdate --list-full-installers | grep 'macOS' | awk '{print ++count " " $0}'

Download OS Installer

#!/bin/bash

# Fetch specific OS version installer
softwareupdate --fetch-full-installer --full-installer-version 12.1

echo "OS installer downloaded successfully"

Install OS Update

#!/bin/bash

# Basic OS update installation
osVersion="$1"
majorVersion=$(echo $osVersion | cut -d "." -f 1)
minorVersion=$(echo $osVersion | cut -d "." -f 2)

if [ $majorVersion == "12" ]; then
    installerPath="Install macOS Monterey.app"
elif [ $majorVersion == "11" ]; then
    installerPath="Install macOS Big Sur.app"
elif [ $minorVersion == "15"* ]; then
    installerPath="Install macOS Catalina.app"
fi

fullPath="/Applications/$installerPath/Contents/Resources/startosinstall"
softwareupdate --fetch-full-installer --full-installer-version $osVersion
echo <Password> | "$fullPath" --agreetolicense --forcequitapps --nointeraction --user <Username> --stdinpass

Enterprise Update Management System

Comprehensive Update Management Tool

#!/bin/bash

# Roundfleet Enterprise macOS Update Management Tool
# Automated patch deployment and compliance monitoring

# Configuration
CONFIG_FILE="/etc/roundfleet/update_policy.conf"
LOG_FILE="/var/log/roundfleet_updates.log"
CACHE_DIR="/Library/Roundfleet/Updates"
REPORT_DIR="/var/log/roundfleet_reports"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$CACHE_DIR" "$REPORT_DIR"

# Default update policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet macOS Update Management Policy
# Version: 2.0

# Update Enforcement
ENFORCE_SECURITY_UPDATES=true
ALLOW_MAJOR_OS_UPDATES=false
AUTO_INSTALL_SECURITY_PATCHES=true
DEFER_MAJOR_UPDATES_DAYS=30

# Scheduling Configuration
UPDATE_CHECK_INTERVAL=86400  # 24 hours
MAINTENANCE_WINDOW_START="02:00"
MAINTENANCE_WINDOW_END="06:00"
WEEKEND_UPDATES_ALLOWED=true
BUSINESS_HOURS_UPDATES=false

# Deployment Strategy
STAGED_ROLLOUT=true
PILOT_GROUP_PERCENTAGE=10
PRODUCTION_DELAY_DAYS=7
EMERGENCY_PATCH_IMMEDIATE=true

# System Requirements
MIN_BATTERY_PERCENTAGE=50
MIN_FREE_SPACE_GB=20
REQUIRE_AC_POWER=true
MAX_REBOOT_ATTEMPTS=3

# Notification Settings
NOTIFY_USERS_BEFORE_UPDATE=true
NOTIFICATION_LEAD_TIME_HOURS=24
FORCE_UPDATE_AFTER_DEFERRALS=5
SEND_COMPLETION_REPORTS=true

# Compatibility Settings
EXCLUDE_BETA_UPDATES=true
VALIDATE_APP_COMPATIBILITY=true
BACKUP_BEFORE_MAJOR_UPDATE=true
EOF

# Source configuration
source "$CONFIG_FILE" 2>/dev/null || true

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Get current macOS version
get_current_version() {
    sw_vers -productVersion
}

# Get available updates
get_available_updates() {
    echo "=== Available Updates ==="
    
    # Check for software updates
    local updates
    updates=$(softwareupdate --list 2>/dev/null)
    
    if echo "$updates" | grep -q "No new software available"; then
        echo "✅ System is up to date"
        return 0
    else
        echo "Available updates:"
        echo "$updates"
        return 1
    fi
}

# Get available OS installers
get_available_installers() {
    echo "=== Available OS Installers ==="
    
    # List full installers
    local installers
    installers=$(softwareupdate --list-full-installers 2>/dev/null)
    
    if [[ -n "$installers" ]]; then
        echo "$installers" | grep 'macOS' | awk '{print ++count " " $0}'
    else
        echo "No OS installers available"
    fi
}

# Check system readiness for updates
check_update_readiness() {
    echo "=== Update Readiness Check ==="
    local issues=0
    local warnings=0
    
    # Check battery level
    local battery_level
    if command -v pmset >/dev/null; then
        battery_level=$(pmset -g batt | grep -Eo "\d+%" | tr -d '%' | head -1)
        
        if [[ -n "$battery_level" && $battery_level -lt $MIN_BATTERY_PERCENTAGE ]]; then
            echo "❌ Battery level too low: ${battery_level}% (min: ${MIN_BATTERY_PERCENTAGE}%)"
            ((issues++))
        else
            echo "✅ Battery level adequate: ${battery_level:-AC Power}%"
        fi
    fi
    
    # Check AC power if required
    if [[ "$REQUIRE_AC_POWER" == "true" ]]; then
        local ac_power
        ac_power=$(pmset -g ps | grep "AC Power" || echo "")
        
        if [[ -z "$ac_power" ]]; then
            echo "❌ AC power required but not connected"
            ((issues++))
        else
            echo "✅ AC power connected"
        fi
    fi
    
    # Check free disk space
    local free_space_gb
    free_space_gb=$(df / | awk 'NR==2 {print int($4/1024/1024)}')
    
    if [[ $free_space_gb -lt $MIN_FREE_SPACE_GB ]]; then
        echo "❌ Insufficient disk space: ${free_space_gb}GB (min: ${MIN_FREE_SPACE_GB}GB)"
        ((issues++))
    else
        echo "✅ Sufficient disk space: ${free_space_gb}GB"
    fi
    
    # Check if system is in maintenance window
    local current_time
    current_time=$(date '+%H:%M')
    
    if [[ "$current_time" > "$MAINTENANCE_WINDOW_START" && "$current_time" < "$MAINTENANCE_WINDOW_END" ]]; then
        echo "✅ Within maintenance window"
    else
        echo "⚠️  Outside maintenance window (current: $current_time)"
        ((warnings++))
    fi
    
    # Check if weekend updates are allowed
    local day_of_week
    day_of_week=$(date '+%u')  # 1=Monday, 7=Sunday
    
    if [[ $day_of_week -gt 5 ]] && [[ "$WEEKEND_UPDATES_ALLOWED" != "true" ]]; then
        echo "❌ Weekend updates not allowed"
        ((issues++))
    fi
    
    echo "Readiness summary: $issues issues, $warnings warnings"
    return $issues
}

# Install security updates
install_security_updates() {
    echo "=== Installing Security Updates ==="
    
    if [[ "$AUTO_INSTALL_SECURITY_PATCHES" != "true" ]]; then
        echo "Security update auto-installation disabled"
        return 0
    fi
    
    # Check readiness
    if ! check_update_readiness >/dev/null; then
        echo "❌ System not ready for updates"
        return 1
    fi
    
    # Install recommended updates
    echo "Installing security and recommended updates..."
    log_action "Starting security update installation"
    
    # Use softwareupdate to install recommended updates
    if softwareupdate --install --recommended --verbose; then
        echo "✅ Security updates installed successfully"
        log_action "Security updates installed successfully"
        
        # Check if restart is required
        if softwareupdate --list | grep -q "restart"; then
            echo "⚠️  System restart required"
            log_action "System restart required after security updates"
        fi
        
        return 0
    else
        echo "❌ Failed to install security updates"
        log_action "FAILED: Security update installation"
        return 1
    fi
}

# Download OS installer
download_os_installer() {
    local target_version="$1"
    
    echo "=== Downloading OS Installer ==="
    echo "Target version: $target_version"
    
    # Validate version format
    if [[ ! "$target_version" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
        echo "❌ Invalid version format: $target_version"
        return 1
    fi
    
    # Download installer
    echo "Downloading macOS $target_version installer..."
    log_action "Downloading macOS installer: $target_version"
    
    if softwareupdate --fetch-full-installer --full-installer-version "$target_version"; then
        echo "✅ macOS installer downloaded successfully"
        log_action "macOS installer downloaded: $target_version"
        
        # Verify installer exists
        local installer_path
        installer_path=$(find /Applications -name "Install macOS*.app" -path "*$target_version*" 2>/dev/null | head -1)
        
        if [[ -n "$installer_path" && -d "$installer_path" ]]; then
            echo "Installer location: $installer_path"
            return 0
        else
            # Check for installer by major version
            local major_version
            major_version=$(echo "$target_version" | cut -d'.' -f1)
            
            case "$major_version" in
                "15")
                    installer_path="/Applications/Install macOS Sequoia.app"
                    ;;
                "14")
                    installer_path="/Applications/Install macOS Sonoma.app"
                    ;;
                "13")
                    installer_path="/Applications/Install macOS Ventura.app"
                    ;;
                "12")
                    installer_path="/Applications/Install macOS Monterey.app"
                    ;;
                "11")
                    installer_path="/Applications/Install macOS Big Sur.app"
                    ;;
                *)
                    echo "❌ Unknown macOS version: $target_version"
                    return 1
                    ;;
            esac
            
            if [[ -d "$installer_path" ]]; then
                echo "Installer found: $installer_path"
                return 0
            else
                echo "❌ Installer not found after download"
                return 1
            fi
        fi
    else
        echo "❌ Failed to download macOS installer"
        log_action "FAILED: macOS installer download for $target_version"
        return 1
    fi
}

# Install major OS update
install_major_update() {
    local target_version="$1"
    local admin_user="$2"
    local admin_password="$3"
    
    echo "=== Installing Major OS Update ==="
    echo "Target version: $target_version"
    echo "Admin user: $admin_user"
    
    if [[ "$ALLOW_MAJOR_OS_UPDATES" != "true" ]]; then
        echo "❌ Major OS updates not allowed by policy"
        return 1
    fi
    
    # Check readiness
    if ! check_update_readiness; then
        echo "❌ System not ready for major update"
        return 1
    fi
    
    # Find installer
    local installer_path
    local major_version
    major_version=$(echo "$target_version" | cut -d'.' -f1)
    
    case "$major_version" in
        "15")
            installer_path="/Applications/Install macOS Sequoia.app"
            ;;
        "14")
            installer_path="/Applications/Install macOS Sonoma.app"
            ;;
        "13")
            installer_path="/Applications/Install macOS Ventura.app"
            ;;
        "12")
            installer_path="/Applications/Install macOS Monterey.app"
            ;;
        "11")
            installer_path="/Applications/Install macOS Big Sur.app"
            ;;
        *)
            echo "❌ Unsupported macOS version: $target_version"
            return 1
            ;;
    esac
    
    if [[ ! -d "$installer_path" ]]; then
        echo "Installer not found, downloading..."
        if ! download_os_installer "$target_version"; then
            return 1
        fi
    fi
    
    # Prepare installation command
    local install_cmd="$installer_path/Contents/Resources/startosinstall"
    local install_args="--agreetolicense --forcequitapps --nointeraction"
    
    # Check if Apple Silicon Mac (requires credentials)
    if system_profiler SPHardwareDataType | grep -q "Apple M"; then
        if [[ -z "$admin_user" || -z "$admin_password" ]]; then
            echo "❌ Apple Silicon Mac requires admin credentials"
            return 1
        fi
        install_args="$install_args --user $admin_user --stdinpass"
    fi
    
    echo "Starting macOS installation..."
    log_action "Starting major OS update to $target_version"
    
    # Execute installation
    if [[ -n "$admin_password" ]]; then
        echo "$admin_password" | "$install_cmd" $install_args
    else
        "$install_cmd" $install_args
    fi
    
    local result=$?
    
    if [[ $result -eq 0 ]]; then
        echo "✅ macOS update initiated successfully"
        log_action "macOS update initiated successfully to $target_version"
        echo "⚠️  System will restart to complete installation"
    else
        echo "❌ Failed to initiate macOS update (exit code: $result)"
        log_action "FAILED: macOS update initiation to $target_version (exit code: $result)"
    fi
    
    return $result
}

# Generate update compliance report
generate_update_report() {
    local report_file="$REPORT_DIR/update_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Update Compliance Report ==="
    
    # Get current system information
    local current_version
    current_version=$(sw_vers -productVersion)
    local build_version
    build_version=$(sw_vers -buildVersion)
    local hardware_model
    hardware_model=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)
    
    # Check for available updates
    local updates_available="false"
    local security_updates_available="false"
    
    if ! softwareupdate --list 2>/dev/null | grep -q "No new software available"; then
        updates_available="true"
        
        if softwareupdate --list 2>/dev/null | grep -i "security\|recommended"; then
            security_updates_available="true"
        fi
    fi
    
    # Calculate days since last update
    local last_update_date
    last_update_date=$(system_profiler SPInstallHistoryDataType | grep "Install Date" | head -1 | awk -F: '{print $2}' | xargs)
    local days_since_update="unknown"
    
    if [[ -n "$last_update_date" ]]; then
        local last_update_epoch
        last_update_epoch=$(date -j -f "%m/%d/%y" "$last_update_date" "+%s" 2>/dev/null || echo "0")
        local current_epoch
        current_epoch=$(date "+%s")
        days_since_update=$(( (current_epoch - last_update_epoch) / 86400 ))
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "update_compliance",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "hardware_model": "$hardware_model",
    "current_os_version": "$current_version",
    "build_version": "$build_version"
  },
  "update_status": {
    "updates_available": $updates_available,
    "security_updates_available": $security_updates_available,
    "days_since_last_update": $days_since_update,
    "last_update_date": "$last_update_date",
    "auto_update_enabled": $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo false)
  },
  "policy_compliance": {
    "security_updates_enforced": $ENFORCE_SECURITY_UPDATES,
    "major_updates_allowed": $ALLOW_MAJOR_OS_UPDATES,
    "auto_install_enabled": $AUTO_INSTALL_SECURITY_PATCHES,
    "staged_rollout_enabled": $STAGED_ROLLOUT
  },
  "system_readiness": {
    "sufficient_battery": true,
    "ac_power_connected": $(pmset -g ps | grep -q "AC Power" && echo true || echo false),
    "sufficient_disk_space": true,
    "in_maintenance_window": false
  }
}
EOF
    
    echo "Update compliance report saved to: $report_file"
    log_action "Update compliance report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Update Management Tool Started ==="
    
    case "${1:-status}" in
        "check")
            get_available_updates
            ;;
        "security")
            install_security_updates
            ;;
        "download")
            download_os_installer "$2"
            ;;
        "install")
            install_major_update "$2" "$3" "$4"
            ;;
        "readiness")
            check_update_readiness
            ;;
        "installers")
            get_available_installers
            ;;
        "report")
            generate_update_report
            ;;
        "status"|*)
            echo "Current macOS version: $(get_current_version)"
            get_available_updates
            ;;
    esac
    
    log_action "=== Update management operation completed ==="
}

# Execute main function
main "$@"

Advanced Update Management

Staged Rollout Management

#!/bin/bash

# Staged rollout management for enterprise deployments
manage_staged_rollout() {
    local update_version="$1"
    local deployment_stage="${2:-pilot}"
    
    echo "=== Staged Rollout Management ==="
    echo "Update version: $update_version"
    echo "Deployment stage: $deployment_stage"
    
    # Define device groups
    local device_serial
    device_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)
    
    # Calculate hash for consistent group assignment
    local hash_value
    hash_value=$(echo "$device_serial" | md5 | cut -c1-2)
    local numeric_hash
    numeric_hash=$(printf "%d" "0x$hash_value")
    local group_percentage
    group_percentage=$((numeric_hash % 100))
    
    case "$deployment_stage" in
        "pilot")
            if [[ $group_percentage -lt $PILOT_GROUP_PERCENTAGE ]]; then
                echo "✅ Device selected for pilot deployment"
                log_action "Device included in pilot group for $update_version"
                return 0
            else
                echo "⏳ Device not in pilot group, waiting for production rollout"
                return 1
            fi
            ;;
        "production")
            echo "✅ Device eligible for production deployment"
            log_action "Device included in production rollout for $update_version"
            return 0
            ;;
        "emergency")
            echo "🚨 Emergency deployment - bypassing staging"
            log_action "Emergency deployment initiated for $update_version"
            return 0
            ;;
        *)
            echo "❌ Unknown deployment stage: $deployment_stage"
            return 1
            ;;
    esac
}

# Usage example:
# manage_staged_rollout "14.2.1" "pilot"

Update Compatibility Checking

#!/bin/bash

# Check application compatibility before major updates
check_app_compatibility() {
    local target_version="$1"
    
    echo "=== Application Compatibility Check ==="
    
    if [[ "$VALIDATE_APP_COMPATIBILITY" != "true" ]]; then
        echo "App compatibility checking disabled"
        return 0
    fi
    
    local incompatible_apps=()
    
    # Check for 32-bit applications (not supported in macOS 10.15+)
    local target_major
    target_major=$(echo "$target_version" | cut -d'.' -f1)
    
    if [[ $target_major -ge 10 ]]; then
        echo "Checking for 32-bit applications..."
        
        # Use system_profiler to find 32-bit apps
        local bit32_apps
        bit32_apps=$(system_profiler SPApplicationsDataType | grep -B1 -A1 "64-Bit (Intel): No" | grep "Location:" | awk -F: '{print $2}' | xargs)
        
        if [[ -n "$bit32_apps" ]]; then
            echo "⚠️  Found 32-bit applications:"
            echo "$bit32_apps"
            incompatible_apps+=("32-bit applications")
        fi
    fi
    
    # Check for known incompatible applications
    local known_incompatible=(
        "/Applications/Adobe CS6"
        "/Applications/Microsoft Office 2011"
        "/Applications/Final Cut Pro 7"
    )
    
    for app_path in "${known_incompatible[@]}"; do
        if [[ -d "$app_path" ]]; then
            echo "⚠️  Found known incompatible app: $app_path"
            incompatible_apps+=("$(basename "$app_path")")
        fi
    done
    
    # Generate compatibility report
    if [[ ${#incompatible_apps[@]} -eq 0 ]]; then
        echo "✅ No compatibility issues detected"
        return 0
    else
        echo "❌ Compatibility issues found:"
        printf '  - %s\n' "${incompatible_apps[@]}"
        
        # Log compatibility issues
        log_action "App compatibility issues found for $target_version: ${incompatible_apps[*]}"
        return 1
    fi
}

check_app_compatibility "14.0"

Automated Backup Before Updates

#!/bin/bash

# Create system backup before major updates
create_pre_update_backup() {
    local backup_destination="${1:-/Volumes/Backup}"
    
    echo "=== Pre-Update Backup ==="
    
    if [[ "$BACKUP_BEFORE_MAJOR_UPDATE" != "true" ]]; then
        echo "Pre-update backup disabled"
        return 0
    fi
    
    # Check backup destination
    if [[ ! -d "$backup_destination" ]]; then
        echo "❌ Backup destination not available: $backup_destination"
        return 1
    fi
    
    # Create Time Machine backup
    echo "Creating Time Machine backup..."
    if tmutil startbackup --auto --block; then
        echo "✅ Time Machine backup completed"
        log_action "Pre-update Time Machine backup completed"
    else
        echo "⚠️  Time Machine backup failed, continuing with update"
        log_action "WARNING: Pre-update Time Machine backup failed"
    fi
    
    # Create system configuration backup
    local config_backup="$backup_destination/roundfleet_config_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    echo "Creating configuration backup..."
    if tar -czf "$config_backup" \
        /etc/roundfleet \
        /Library/Preferences \
        /System/Library/LaunchDaemons/com.roundfleet.* \
        2>/dev/null; then
        echo "✅ Configuration backup created: $config_backup"
        log_action "Configuration backup created: $config_backup"
    else
        echo "⚠️  Configuration backup failed"
        log_action "WARNING: Configuration backup failed"
    fi
    
    return 0
}

create_pre_update_backup

Monitoring and Compliance

Update Compliance Monitoring

#!/bin/bash

# Monitor update compliance across fleet
monitor_update_compliance() {
    echo "=== Update Compliance Monitoring ==="
    
    local current_version
    current_version=$(sw_vers -productVersion)
    
    # Check against security baselines
    local security_baseline="14.2.1"  # Example baseline
    
    if [[ "$(printf '%s\n' "$security_baseline" "$current_version" | sort -V | head -1)" != "$security_baseline" ]]; then
        echo "❌ Below security baseline (current: $current_version, required: $security_baseline)"
        log_action "COMPLIANCE VIOLATION: Below security baseline $security_baseline"
        
        # Trigger remediation if enabled
        if [[ "$ENFORCE_SECURITY_UPDATES" == "true" ]]; then
            echo "Initiating automatic remediation..."
            install_security_updates
        fi
    else
        echo "✅ Meets security baseline requirements"
    fi
    
    # Check for overdue updates
    local last_check
    last_check=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate LastSuccessfulDate 2>/dev/null || echo "")
    
    if [[ -n "$last_check" ]]; then
        local days_since_check
        days_since_check=$(( ($(date +%s) - $(date -j -f "%Y-%m-%d %H:%M:%S %z" "$last_check" +%s 2>/dev/null || echo 0)) / 86400 ))
        
        if [[ $days_since_check -gt 7 ]]; then
            echo "⚠️  Updates not checked for $days_since_check days"
            log_action "WARNING: Updates not checked for $days_since_check days"
        fi
    fi
}

monitor_update_compliance

Emergency Patch Deployment

#!/bin/bash

# Emergency patch deployment for critical security updates
deploy_emergency_patch() {
    local patch_version="$1"
    local override_policies="${2:-false}"
    
    echo "=== Emergency Patch Deployment ==="
    echo "Patch version: $patch_version"
    echo "Override policies: $override_policies"
    
    log_action "EMERGENCY: Deploying critical patch $patch_version"
    
    # Override normal restrictions for emergency patches
    if [[ "$override_policies" == "true" ]]; then
        # Temporarily modify configuration
        local original_config
        original_config=$(cat "$CONFIG_FILE")
        
        # Emergency configuration
        cat > "$CONFIG_FILE" << 'EOF'
ENFORCE_SECURITY_UPDATES=true
AUTO_INSTALL_SECURITY_PATCHES=true
EMERGENCY_PATCH_IMMEDIATE=true
REQUIRE_AC_POWER=false
MIN_BATTERY_PERCENTAGE=20
BUSINESS_HOURS_UPDATES=true
EOF
        
        # Install emergency patch
        if install_security_updates; then
            echo "✅ Emergency patch deployed successfully"
            log_action "Emergency patch $patch_version deployed successfully"
        else
            echo "❌ Emergency patch deployment failed"
            log_action "CRITICAL: Emergency patch $patch_version deployment FAILED"
        fi
        
        # Restore original configuration
        echo "$original_config" > "$CONFIG_FILE"
    else
        # Standard emergency deployment
        install_security_updates
    fi
}

# Example usage:
# deploy_emergency_patch "14.2.1" "true"

Important Configuration Notes

macOS Update Tools

  • softwareupdate - Command-line Software Update utility
  • startosinstall - Direct OS installation tool
  • system_profiler - System information and update history
  • tmutil - Time Machine backup utility
  • pmset - Power management settings

Apple Silicon Considerations

  • Admin credentials required - Updates need user authentication
  • Secure Boot policies - May affect update installation
  • Recovery mode options - Different from Intel Macs
  • Reduced kernel extensions - System extension model

Best Practices for Enterprise

  1. Staged Deployment Strategy

    • Test updates on pilot group first
    • Monitor for issues before full rollout
    • Maintain rollback capabilities
  2. Compliance Management

    • Define security baselines
    • Monitor update status regularly
    • Automate compliance reporting
  3. Risk Mitigation

    • Backup before major updates
    • Test application compatibility
    • Plan for emergency patches
  4. User Communication

    • Notify users of scheduled updates
    • Provide clear maintenance windows
    • Offer deferral options within policy limits

Troubleshooting Common Issues

  • Insufficient disk space - Clean up before updates or increase storage
  • Power requirements - Ensure AC power for major updates
  • Network connectivity - Verify access to Apple's update servers
  • Authentication failures - Check admin credentials on Apple Silicon
  • Installation failures - Review system logs and compatibility

Remember to test update procedures thoroughly in a non-production environment before deploying across your entire Roundfleet.

Login Window Customization on macOS

Customize and secure the login window on your Roundfleet devices to enhance security, branding, and user experience. This tutorial covers user list management, power option control, custom messages, and enterprise login window configuration.

Understanding macOS Login Window

The macOS login window is the first interface users encounter when starting their device. It provides several customization options:

  • User display modes - Show user list or username/password fields
  • Power options - Control shutdown, restart, and sleep buttons
  • Custom messages - Display organizational notices or branding
  • Security settings - Hide sensitive information and control access

Enterprise Considerations

Login window customization is crucial for enterprise security:

  • Hide user lists to prevent user enumeration
  • Disable power options to prevent unauthorized shutdowns
  • Display security notices for compliance requirements
  • Brand the interface for organizational identity

Basic Login Window Configuration

Display User List in Login Window

#!/bin/bash

# Show the list of users in the login window
defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false

echo "User list display enabled in login window"

Display Username/Password Dialog

#!/bin/bash

# Show username and password dialog instead of user list
defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true

echo "Username/password dialog enabled in login window"

Hide Power Options

#!/bin/bash

# Hide shutdown button
defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true

# Hide restart button
defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true

# Hide sleep button
defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true

echo "All power options hidden from login window"

Enable Power Options

#!/bin/bash

# Enable shutdown button
defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false

# Enable restart button
defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false

# Enable sleep button
defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false

echo "All power options enabled in login window"

Display Custom Message

#!/bin/bash

# Display a custom message on the login window
MESSAGE="Your device is managed by Roundfleet. Contact IT for assistance."
defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$MESSAGE"

echo "Custom message set for login window"

Advanced Login Window Management

Comprehensive Login Window Configuration

#!/bin/bash

# Advanced login window configuration with validation
configure_login_window() {
    local config_type="$1"
    local custom_message="$2"
    
    # Validate admin privileges
    if [[ $EUID -ne 0 ]]; then
        echo "Error: This script requires administrator privileges"
        echo "Please run with sudo: sudo $0"
        exit 1
    fi
    
    case "$config_type" in
        "secure")
            echo "Applying secure login window configuration..."
            
            # Hide user list for security
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            
            # Disable all power options
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Set security message
            local security_msg="Authorized Personnel Only - All Activity Monitored"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$security_msg"
            
            echo "✓ Secure configuration applied"
            ;;
        "corporate")
            echo "Applying corporate login window configuration..."
            
            # Show user list for convenience
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            
            # Allow restart but disable shutdown and sleep
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Set corporate message
            local corp_msg="${custom_message:-Property of Roundfleet Corporation}"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$corp_msg"
            
            echo "✓ Corporate configuration applied"
            ;;
        "kiosk")
            echo "Applying kiosk login window configuration..."
            
            # Hide user list
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            
            # Disable all power options
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Hide additional elements for kiosk mode
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers true
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            
            # Set kiosk message
            local kiosk_msg="Kiosk Mode - Authorized Access Only"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$kiosk_msg"
            
            echo "✓ Kiosk configuration applied"
            ;;
        "standard")
            echo "Applying standard login window configuration..."
            
            # Show user list
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            
            # Enable all power options
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
            
            # Clear custom message
            defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || true
            
            echo "✓ Standard configuration applied"
            ;;
        *)
            echo "Error: Unknown configuration type '$config_type'"
            echo "Available types: secure, corporate, kiosk, standard"
            return 1
            ;;
    esac
    
    # Verify configuration
    verify_login_window_config
}

# Verify current login window configuration
verify_login_window_config() {
    echo ""
    echo "=== Current Login Window Configuration ==="
    
    # Check user display mode
    local show_fullname
    show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    
    if [[ "$show_fullname" == "true" ]]; then
        echo "User Display: Username/Password Dialog"
    else
        echo "User Display: User List"
    fi
    
    # Check power options
    local shutdown_disabled
    shutdown_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || echo "false")
    echo "Shutdown Button: $([ "$shutdown_disabled" == "true" ] && echo "Hidden" || echo "Visible")"
    
    local restart_disabled
    restart_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || echo "false")
    echo "Restart Button: $([ "$restart_disabled" == "true" ] && echo "Hidden" || echo "Visible")"
    
    local sleep_disabled
    sleep_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || echo "false")
    echo "Sleep Button: $([ "$sleep_disabled" == "true" ] && echo "Hidden" || echo "Visible")"
    
    # Check custom message
    local login_text
    login_text=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "None")
    echo "Custom Message: $login_text"
}

# Usage examples
configure_login_window "corporate" "Welcome to Roundfleet Enterprise"

Login Window Branding and Customization

#!/bin/bash

# Advanced login window branding
customize_login_branding() {
    local company_name="$1"
    local support_info="$2"
    local logo_path="$3"
    
    echo "=== Customizing Login Window Branding ==="
    
    # Set company message
    if [[ -n "$company_name" ]]; then
        local branded_message="Property of $company_name"
        if [[ -n "$support_info" ]]; then
            branded_message="$branded_message | Support: $support_info"
        fi
        
        defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$branded_message"
        echo "✓ Company branding message set"
    fi
    
    # Set custom desktop background for login window
    if [[ -n "$logo_path" && -f "$logo_path" ]]; then
        defaults write /Library/Preferences/com.apple.loginwindow DesktopPicture "$logo_path"
        echo "✓ Custom background image set"
    fi
    
    # Configure additional branding options
    setup_login_window_styling "$company_name"
}

# Setup advanced login window styling
setup_login_window_styling() {
    local company_name="$1"
    
    # Hide computer name for cleaner appearance
    defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName
    
    # Configure login window appearance
    defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
    
    # Set custom computer name display
    if [[ -n "$company_name" ]]; then
        scutil --set ComputerName "$company_name Workstation"
        scutil --set LocalHostName "$company_name-Mac"
    fi
    
    echo "✓ Login window styling configured"
}

# Usage
customize_login_branding "Roundfleet Corporation" "[email protected]" "/System/Library/Desktop Pictures/Big Sur.heic"

Security-Focused Login Configuration

#!/bin/bash

# High-security login window configuration
apply_security_hardening() {
    local security_level="$1"
    
    echo "=== Applying Security Hardening: $security_level ==="
    
    case "$security_level" in
        "maximum")
            # Hide all user information
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers true
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            defaults write /Library/Preferences/com.apple.loginwindow HideAdminUsers true
            
            # Disable all power options
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Hide additional UI elements
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu false
            defaults write /Library/Preferences/com.apple.loginwindow PowerOffDisabledWhileLoggedIn true
            
            # Set security warning
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "RESTRICTED ACCESS - AUTHORIZED PERSONNEL ONLY"
            
            echo "✓ Maximum security configuration applied"
            ;;
        "high")
            # Hide user list but allow some functionality
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers false
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            
            # Disable shutdown and sleep, allow restart
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Set moderate security message
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Corporate Device - Authorized Users Only"
            
            echo "✓ High security configuration applied"
            ;;
        "moderate")
            # Show user list but control power options
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers false
            
            # Allow restart, disable shutdown and sleep
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Set informational message
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Managed Device - Contact IT for Support"
            
            echo "✓ Moderate security configuration applied"
            ;;
        *)
            echo "Error: Unknown security level '$security_level'"
            echo "Available levels: maximum, high, moderate"
            return 1
            ;;
    esac
}

# Usage
apply_security_hardening "high"

Enterprise Login Window Management System

#!/bin/bash

# Roundfleet Login Window Management Tool
# Comprehensive login window configuration and monitoring for fleet devices

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_loginwindow.log"
REPORT_DIR="/etc/roundfleet/reports/loginwindow"
CONFIG_DIR="/etc/roundfleet/loginwindow"
TEMPLATE_DIR="/etc/roundfleet/templates/loginwindow"

# Create directories if they don't exist
mkdir -p "$REPORT_DIR" "$CONFIG_DIR" "$TEMPLATE_DIR"

# Login window policy templates
declare -A LOGIN_POLICIES=(
    ["corporate_standard"]="user_list,restart_only,company_branding,moderate_security"
    ["corporate_secure"]="username_dialog,no_power,security_message,high_security"
    ["kiosk_mode"]="username_dialog,no_power,kiosk_branding,maximum_security"
    ["public_access"]="user_list,all_power,public_notice,low_security"
    ["executive"]="username_dialog,restart_only,executive_branding,high_security"
    ["guest_network"]="user_list,no_power,guest_notice,moderate_security"
    ["development"]="user_list,all_power,dev_environment,low_security"
    ["classroom"]="user_list,restart_only,educational_message,moderate_security"
    ["healthcare"]="username_dialog,no_power,hipaa_notice,maximum_security"
    ["financial"]="username_dialog,no_power,compliance_notice,maximum_security"
)

# Message templates for different scenarios
declare -A MESSAGE_TEMPLATES=(
    ["security_warning"]="RESTRICTED ACCESS - AUTHORIZED PERSONNEL ONLY - ALL ACTIVITY MONITORED"
    ["corporate_standard"]="Property of {COMPANY} | IT Support: {SUPPORT_CONTACT}"
    ["compliance_notice"]="This system contains confidential information. Unauthorized access is prohibited."
    ["guest_notice"]="Guest Access | Please contact reception for assistance"
    ["kiosk_mode"]="Kiosk Terminal | For assistance press F1"
    ["maintenance"]="System Under Maintenance | Contact IT Department"
    ["emergency"]="Emergency Access Only | Security Incident in Progress"
    ["educational"]="Educational Device | Students must follow acceptable use policy"
    ["hipaa_notice"]="HIPAA Protected System | Authorized Healthcare Personnel Only"
    ["financial_compliance"]="Financial Data System | SOX Compliance Required"
)

# Logging function
log_action() {
    local message="$1"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] $message" | tee -a "$LOG_FILE"
}

# Advanced login window policy enforcement
enforce_login_policy() {
    local policy_name="$1"
    local company_name="${2:-Roundfleet}"
    local support_contact="${3:-IT Department}"
    local dry_run="${4:-false}"
    
    log_action "Enforcing login window policy: $policy_name (dry_run: $dry_run)"
    
    if [[ -z "${LOGIN_POLICIES[$policy_name]}" ]]; then
        log_action "ERROR: Unknown policy '$policy_name'"
        echo "Available policies: ${!LOGIN_POLICIES[*]}"
        return 1
    fi
    
    # Parse policy configuration
    IFS=',' read -ra POLICY_PARTS <<< "${LOGIN_POLICIES[$policy_name]}"
    local user_display="${POLICY_PARTS[0]}"
    local power_options="${POLICY_PARTS[1]}"
    local branding_type="${POLICY_PARTS[2]}"
    local security_level="${POLICY_PARTS[3]}"
    
    echo "=== Enforcing Policy: $policy_name ==="
    echo "User Display: $user_display"
    echo "Power Options: $power_options"
    echo "Branding: $branding_type"
    echo "Security Level: $security_level"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "DRY RUN MODE - No changes will be applied"
        return 0
    fi
    
    # Apply user display settings
    apply_user_display_settings "$user_display"
    
    # Apply power option settings
    apply_power_option_settings "$power_options"
    
    # Apply branding and messaging
    apply_branding_settings "$branding_type" "$company_name" "$support_contact"
    
    # Apply security configurations
    apply_security_settings "$security_level"
    
    # Generate policy compliance report
    local report_file="$REPORT_DIR/policy_enforcement_${policy_name}_$(date +%Y%m%d_%H%M%S).json"
    generate_policy_report "$policy_name" "$report_file"
    
    log_action "Policy enforcement completed: $report_file"
    echo "$report_file"
}

# Apply user display settings
apply_user_display_settings() {
    local display_type="$1"
    
    case "$display_type" in
        "user_list")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers false
            echo "✓ User list display enabled"
            ;;
        "username_dialog")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            echo "✓ Username/password dialog enabled"
            ;;
        "hidden_users")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers true
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            echo "✓ All users hidden from display"
            ;;
    esac
}

# Apply power option settings
apply_power_option_settings() {
    local power_config="$1"
    
    case "$power_config" in
        "all_power")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
            echo "✓ All power options enabled"
            ;;
        "restart_only")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            echo "✓ Only restart option enabled"
            ;;
        "no_power")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            echo "✓ All power options disabled"
            ;;
    esac
}

# Apply branding and messaging settings
apply_branding_settings() {
    local branding_type="$1"
    local company_name="$2"
    local support_contact="$3"
    
    local message=""
    
    case "$branding_type" in
        "company_branding")
            message="${MESSAGE_TEMPLATES[corporate_standard]}"
            message="${message/\{COMPANY\}/$company_name}"
            message="${message/\{SUPPORT_CONTACT\}/$support_contact}"
            ;;
        "security_message")
            message="${MESSAGE_TEMPLATES[security_warning]}"
            ;;
        "kiosk_branding")
            message="${MESSAGE_TEMPLATES[kiosk_mode]}"
            ;;
        "executive_branding")
            message="Executive Workstation | $company_name | Confidential"
            ;;
        "guest_notice")
            message="${MESSAGE_TEMPLATES[guest_notice]}"
            ;;
        "educational_message")
            message="${MESSAGE_TEMPLATES[educational]}"
            ;;
        "hipaa_notice")
            message="${MESSAGE_TEMPLATES[hipaa_notice]}"
            ;;
        "compliance_notice")
            message="${MESSAGE_TEMPLATES[financial_compliance]}"
            ;;
        *)
            message="Managed by $company_name"
            ;;
    esac
    
    if [[ -n "$message" ]]; then
        defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$message"
        echo "✓ Custom message applied: $message"
    fi
}

# Apply security-specific settings
apply_security_settings() {
    local security_level="$1"
    
    case "$security_level" in
        "maximum_security")
            # Hide computer information
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo ""
            
            # Disable input menu
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu false
            
            # Disable auto login
            defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser 2>/dev/null || true
            
            # Enable login window delay
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ Maximum security settings applied"
            ;;
        "high_security")
            # Show minimal computer info
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName
            
            # Enable input menu for language support
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            
            # Disable guest account
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ High security settings applied"
            ;;
        "moderate_security")
            # Standard security with some convenience features
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ Moderate security settings applied"
            ;;
        "low_security")
            # Minimal restrictions for convenience
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            
            echo "✓ Low security settings applied"
            ;;
    esac
}

# Generate comprehensive policy compliance report
generate_policy_report() {
    local policy_name="$1"
    local report_file="$2"
    
    # Get current login window settings
    local show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    local shutdown_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || echo "false")
    local restart_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || echo "false")
    local sleep_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || echo "false")
    local login_text=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "")
    local hide_local_users=$(defaults read /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || echo "false")
    local guest_enabled=$(defaults read /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || echo "false")
    
    cat > "$report_file" << EOF
{
    "policy_report": {
        "policy_name": "$policy_name",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION",
        "current_settings": {
            "show_fullname": $show_fullname,
            "shutdown_disabled": $shutdown_disabled,
            "restart_disabled": $restart_disabled,
            "sleep_disabled": $sleep_disabled,
            "custom_message": "$login_text",
            "hide_local_users": $hide_local_users,
            "guest_enabled": $guest_enabled
        },
        "display_mode": "$([ "$show_fullname" == "true" ] && echo "username_dialog" || echo "user_list")",
        "security_level": "unknown",
        "compliance_status": "compliant"
    }
}
EOF
    
    log_action "Policy report generated: $report_file"
}

# Monitor login window configuration
monitor_login_window() {
    local detailed="${1:-false}"
    
    echo "=== Login Window Configuration Monitor ==="
    
    # Basic configuration check
    local show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    local display_mode=$([ "$show_fullname" == "true" ] && echo "Username/Password Dialog" || echo "User List")
    
    echo "Display Mode: $display_mode"
    
    # Power options status
    local shutdown_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null)" == "true" ] && echo "Hidden" || echo "Visible")
    local restart_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null)" == "true" ] && echo "Hidden" || echo "Visible")
    local sleep_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null)" == "true" ] && echo "Hidden" || echo "Visible")
    
    echo "Power Options:"
    echo "  Shutdown Button: $shutdown_status"
    echo "  Restart Button: $restart_status"
    echo "  Sleep Button: $sleep_status"
    
    # Custom message
    local custom_message=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "None")
    echo "Custom Message: $custom_message"
    
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "=== Detailed Configuration ==="
        
        # Additional settings
        local hide_local=$(defaults read /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || echo "false")
        local hide_mobile=$(defaults read /Library/Preferences/com.apple.loginwindow HideMobileAccounts 2>/dev/null || echo "false")
        local guest_enabled=$(defaults read /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || echo "false")
        local admin_info=$(defaults read /Library/Preferences/com.apple.loginwindow AdminHostInfo 2>/dev/null || echo "DSStatus")
        
        echo "Advanced Settings:"
        echo "  Hide Local Users: $hide_local"
        echo "  Hide Mobile Accounts: $hide_mobile"
        echo "  Guest Account Enabled: $guest_enabled"
        echo "  Admin Host Info: $admin_info"
        
        # Check for custom background
        local desktop_picture=$(defaults read /Library/Preferences/com.apple.loginwindow DesktopPicture 2>/dev/null || echo "Default")
        echo "  Desktop Picture: $desktop_picture"
    fi
}

# Main execution function
main() {
    local action="${1:-status}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Roundfleet Login Window Management Started ==="
    log_action "Action: $action"
    
    # Ensure required privileges for configuration changes
    if [[ "$action" != "status" && "$action" != "help" && $EUID -ne 0 ]]; then
        echo "Error: This action requires administrator privileges"
        echo "Please run with sudo: sudo $0 $*"
        exit 1
    fi
    
    case "$action" in
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Available policies: ${!LOGIN_POLICIES[*]}"
                exit 1
            fi
            enforce_login_policy "$param1" "$param2" "$param3" "$param4"
            ;;
        "secure")
            apply_security_hardening "${param1:-high}"
            ;;
        "message")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 message <message_text>"
                exit 1
            fi
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$param1"
            echo "✓ Custom message set: $param1"
            ;;
        "power")
            case "$param1" in
                "disable")
                    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
                    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
                    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
                    echo "✓ All power options disabled"
                    ;;
                "enable")
                    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
                    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
                    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
                    echo "✓ All power options enabled"
                    ;;
                *)
                    echo "Usage: $0 power <enable|disable>"
                    exit 1
                    ;;
            esac
            ;;
        "display")
            case "$param1" in
                "userlist")
                    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
                    echo "✓ User list display enabled"
                    ;;
                "dialog")
                    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
                    echo "✓ Username/password dialog enabled"
                    ;;
                *)
                    echo "Usage: $0 display <userlist|dialog>"
                    exit 1
                    ;;
            esac
            ;;
        "status")
            monitor_login_window "$param1"
            ;;
        "reset")
            echo "Resetting login window to defaults..."
            defaults delete /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || true
            echo "✓ Login window reset to system defaults"
            ;;
        "help")
            echo "Usage: $0 [action] [options...]"
            echo "Actions:"
            echo "  policy <policy_name> [company] [support] [dry_run] - Apply policy"
            echo "  secure <level> - Apply security hardening (maximum/high/moderate)"
            echo "  message <text> - Set custom login message"
            echo "  power <enable|disable> - Control power button visibility"
            echo "  display <userlist|dialog> - Set user display mode"
            echo "  status [detailed] - Show current configuration"
            echo "  reset - Reset to system defaults"
            echo "  help - Show this help"
            echo ""
            echo "Policies: ${!LOGIN_POLICIES[*]}"
            echo "Message Templates: ${!MESSAGE_TEMPLATES[*]}"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
    
    log_action "=== Login window management completed ==="
}

# Execute main function
main "$@"

Login Window Security Best Practices

Corporate Security Configuration

#!/bin/bash

# Implement corporate login window security
implement_corporate_security() {
    echo "=== Implementing Corporate Login Window Security ==="
    
    # Hide user enumeration
    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
    
    # Disable power options to prevent unauthorized shutdowns
    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
    
    # Allow restart for updates (optional)
    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
    
    # Set corporate security message
    defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Corporate Property - Authorized Personnel Only"
    
    # Disable guest account
    defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
    
    # Hide computer information
    defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo ""
    
    echo "✓ Corporate security configuration applied"
}

implement_corporate_security

Compliance and Audit Configuration

#!/bin/bash

# Configure login window for compliance requirements
configure_compliance_login() {
    local compliance_type="$1"
    
    case "$compliance_type" in
        "hipaa")
            # Healthcare compliance configuration
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "HIPAA Protected System - Healthcare Personnel Only"
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            echo "✓ HIPAA compliance configuration applied"
            ;;
        "pci_dss")
            # Payment card industry compliance
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "PCI DSS Secure Environment - Authorized Access Only"
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            echo "✓ PCI DSS compliance configuration applied"
            ;;
        "sox")
            # Financial compliance
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Financial Data System - SOX Compliance Required"
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            echo "✓ SOX compliance configuration applied"
            ;;
        *)
            echo "Unknown compliance type: $compliance_type"
            return 1
            ;;
    esac
}

# Usage
configure_compliance_login "hipaa"

Troubleshooting Login Window Issues

Verify Configuration

#!/bin/bash

# Comprehensive login window configuration verification
verify_login_config() {
    echo "=== Login Window Configuration Verification ==="
    
    # Check all current settings
    echo "Current Settings:"
    echo "  Show Full Name: $(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo 'Not Set')"
    echo "  Shutdown Disabled: $(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || echo 'Not Set')"
    echo "  Restart Disabled: $(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || echo 'Not Set')"
    echo "  Sleep Disabled: $(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || echo 'Not Set')"
    echo "  Login Text: $(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo 'Not Set')"
    echo "  Guest Enabled: $(defaults read /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || echo 'Not Set')"
    echo "  Hide Local Users: $(defaults read /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || echo 'Not Set')"
    
    # Check file permissions
    echo ""
    echo "File Permissions:"
    ls -la /Library/Preferences/com.apple.loginwindow.plist 2>/dev/null || echo "Login window plist not found"
    
    # Verify settings will take effect
    echo ""
    echo "Verification Tests:"
    if defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME &>/dev/null; then
        echo "✓ Login window preferences are readable"
    else
        echo "⚠ Login window preferences may not be configured"
    fi
}

verify_login_config

Reset to Defaults

#!/bin/bash

# Reset login window to system defaults
reset_login_window() {
    echo "=== Resetting Login Window to Defaults ==="
    
    # Remove all custom settings
    defaults delete /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow HideMobileAccounts 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow AdminHostInfo 2>/dev/null || true
    defaults delete /Library/Preferences/com.apple.loginwindow DesktopPicture 2>/dev/null || true
    
    echo "✓ Login window reset to system defaults"
    echo "Note: Changes will take effect after logout or restart"
}

reset_login_window

Important Notes

  • Administrator privileges required for login window modifications
  • Changes take effect after logout or restart
  • Test thoroughly on individual devices before fleet deployment
  • Backup settings before making changes
  • Security implications - Consider hiding user lists in high-security environments
  • User experience - Balance security with usability
  • Compliance requirements - Some industries require specific login window configurations
  • Special characters - Avoid exclamation marks in custom messages due to shell interpretation

Login History Management on macOS

Monitor and analyze user login activity across your Roundfleet devices using advanced command-line tools. This tutorial covers login history tracking, user session analysis, security auditing, and enterprise-grade compliance monitoring with comprehensive reporting capabilities.

Understanding macOS Login History Management

macOS provides several powerful tools for tracking user login activity:

  • who - Shows currently logged-in users and brief login history
  • last - Displays detailed login history with session information
  • dscl - Directory Services command line utility for user management
  • w - Extended user activity information with system load
  • finger - User information and login details (if available)

These tools access system logs and user databases to provide comprehensive login tracking capabilities.

Basic Login History Commands

Brief Login History with who

#!/bin/bash

# Display brief login history
get_brief_login_history() {
    echo "=== Brief Login History ==="
    who
    echo ""
    
    # Alternative with timestamps
    echo "=== Current User Sessions ==="
    who -u
}

# Execute basic login check
get_brief_login_history

Detailed Login History with last

#!/bin/bash

# Display detailed login history
get_detailed_login_history() {
    echo "=== Detailed Login History ==="
    last
    echo ""
    
    # Show last 10 login entries
    echo "=== Recent 10 Login Sessions ==="
    last -10
    echo ""
    
    # Show login history for today
    echo "=== Today's Login Sessions ==="
    last -t "$(date '+%Y%m%d%H%M%S')"
}

# Execute detailed login check
get_detailed_login_history

Check Specific User Login History

#!/bin/bash

# Get last login time for specific user
check_user_login() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage: check_user_login <username>"
        return 1
    fi
    
    echo "=== Last Login for User: $username ==="
    last -1 "$username"
    echo ""
    
    # Additional user information
    echo "=== User Account Information ==="
    dscl . -read "/Users/$username" RealName 2>/dev/null || echo "User not found"
    dscl . -read "/Users/$username" UniqueID 2>/dev/null || echo "UID not available"
}

# Example usage
# check_user_login "john.doe"

Advanced Login History Analysis

Comprehensive User Session Analysis

#!/bin/bash

# Advanced login history analysis with security insights
analyze_login_patterns() {
    echo "=== Comprehensive Login Analysis ==="
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo "=================================="
    echo ""
    
    # Current active sessions
    echo "1. ACTIVE USER SESSIONS:"
    echo "------------------------"
    who -u | while IFS= read -r line; do
        echo "  $line"
    done
    echo ""
    
    # Recent login activity (last 24 hours)
    echo "2. RECENT LOGIN ACTIVITY (24 hours):"
    echo "------------------------------------"
    local yesterday
    yesterday=$(date -v-1d '+%Y%m%d%H%M%S' 2>/dev/null || date -d 'yesterday' '+%Y%m%d%H%M%S' 2>/dev/null)
    
    if [[ -n "$yesterday" ]]; then
        last -t "$yesterday" | head -20
    else
        last -20
    fi
    echo ""
    
    # Failed login attempts (if available in logs)
    echo "3. FAILED LOGIN ATTEMPTS:"
    echo "-------------------------"
    grep "authentication failure" /var/log/system.log 2>/dev/null | tail -10 || echo "No recent failures found"
    echo ""
    
    # Login frequency analysis
    echo "4. LOGIN FREQUENCY BY USER:"
    echo "---------------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    echo ""
    
    # Remote vs local logins
    echo "5. LOGIN SOURCE ANALYSIS:"
    echo "-------------------------"
    echo "Console logins:"
    last | grep -c "console" || echo "0"
    echo "Remote logins:"
    last | grep -v "console" | grep -v "wtmp begins" | wc -l | tr -d ' '
}

# Execute comprehensive analysis
analyze_login_patterns

User Account Discovery

#!/bin/bash

# List all users and their login status
discover_users() {
    echo "=== User Account Discovery ==="
    echo ""
    
    # All users from directory services
    echo "1. ALL SYSTEM USERS:"
    echo "-------------------"
    dscl . list /Users | grep -v "^_" | grep -v "^root" | grep -v "^daemon" | grep -v "^nobody"
    echo ""
    
    # Users with UID >= 500 (typically regular users)
    echo "2. REGULAR USER ACCOUNTS:"
    echo "------------------------"
    dscl . list /Users UniqueID | awk '$2 >= 500 {print $1, "(UID: " $2 ")"}'
    echo ""
    
    # Users with recent login activity
    echo "3. USERS WITH RECENT LOGIN ACTIVITY:"
    echo "------------------------------------"
    last | awk '{print $1}' | sort | uniq | grep -v "wtmp" | grep -v "^$" | head -10
    echo ""
    
    # Home directories
    echo "4. USER HOME DIRECTORIES:"
    echo "------------------------"
    ls -la /Users/ | grep -v "^total" | grep -v "Shared" | awk '{print $9, $3, $4}' | grep -v "^$"
}

# Execute user discovery
discover_users

Enterprise Login History Management System

#!/bin/bash

# Roundfleet Enterprise Login History Management System
# Comprehensive user activity monitoring and security auditing

# Configuration
LOG_FILE="/var/log/roundfleet_login_history.log"
REPORT_DIR="/var/reports/roundfleet/login_history"
CONFIG_FILE="/etc/roundfleet/login_monitoring.conf"
ALERT_THRESHOLD_FAILED_LOGINS=5
ALERT_THRESHOLD_UNUSUAL_HOURS=22  # Alert for logins after 10 PM

# Create directory structure
setup_directories() {
    mkdir -p "$(dirname "$LOG_FILE")" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")"
    touch "$LOG_FILE"
}

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Generate comprehensive login report
generate_login_report() {
    local report_file="$REPORT_DIR/login_report_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Generating comprehensive login history report: $report_file"
    
    {
        echo "{"
        echo "  \"report_type\": \"login_history\","
        echo "  \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
        echo "  \"hostname\": \"$(hostname)\","
        echo "  \"system_info\": {"
        echo "    \"macos_version\": \"$(sw_vers -productVersion)\","
        echo "    \"uptime\": \"$(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')\","
        echo "    \"current_users\": $(who | wc -l | tr -d ' ')"
        echo "  },"
        
        # Active sessions
        echo "  \"active_sessions\": ["
        local first_session=true
        who -u | while IFS= read -r line; do
            if [[ "$first_session" == "false" ]]; then
                echo ","
            fi
            first_session=false
            
            local user terminal login_time pid
            user=$(echo "$line" | awk '{print $1}')
            terminal=$(echo "$line" | awk '{print $2}')
            login_time=$(echo "$line" | awk '{print $3, $4}')
            pid=$(echo "$line" | awk '{print $6}')
            
            echo "    {"
            echo "      \"user\": \"$user\","
            echo "      \"terminal\": \"$terminal\","
            echo "      \"login_time\": \"$login_time\","
            echo "      \"pid\": \"$pid\""
            echo -n "    }"
        done
        echo ""
        echo "  ],"
        
        # Recent login history
        echo "  \"recent_logins\": ["
        local first_login=true
        last -20 | grep -v "wtmp begins" | while IFS= read -r line; do
            if [[ -n "$line" ]]; then
                if [[ "$first_login" == "false" ]]; then
                    echo ","
                fi
                first_login=false
                
                local user terminal source login_date login_time logout_info
                user=$(echo "$line" | awk '{print $1}')
                terminal=$(echo "$line" | awk '{print $2}')
                source=$(echo "$line" | awk '{print $3}')
                login_date=$(echo "$line" | awk '{print $4, $5, $6}')
                login_time=$(echo "$line" | awk '{print $7}')
                logout_info=$(echo "$line" | awk '{print $9, $10}')
                
                echo "    {"
                echo "      \"user\": \"$user\","
                echo "      \"terminal\": \"$terminal\","
                echo "      \"source\": \"$source\","
                echo "      \"login_date\": \"$login_date\","
                echo "      \"login_time\": \"$login_time\","
                echo "      \"logout_info\": \"$logout_info\""
                echo -n "    }"
            fi
        done
        echo ""
        echo "  ],"
        
        # User statistics
        echo "  \"user_statistics\": {"
        local total_users
        total_users=$(dscl . list /Users | grep -v "^_" | wc -l | tr -d ' ')
        echo "    \"total_system_users\": $total_users,"
        
        local regular_users
        regular_users=$(dscl . list /Users UniqueID | awk '$2 >= 500' | wc -l | tr -d ' ')
        echo "    \"regular_users\": $regular_users,"
        
        local active_login_users
        active_login_users=$(last | awk '{print $1}' | sort | uniq | grep -v "wtmp" | grep -v "^$" | wc -l | tr -d ' ')
        echo "    \"users_with_login_history\": $active_login_users"
        echo "  }"
        echo "}"
    } > "$report_file"
    
    log_action "Login history report generated successfully"
    echo "$report_file"
}

# Monitor for suspicious login activity
monitor_suspicious_activity() {
    log_action "Starting suspicious login activity monitoring..."
    
    local alerts=()
    
    # Check for unusual login times (configurable)
    local current_hour
    current_hour=$(date +%H)
    
    if [[ "$current_hour" -ge "$ALERT_THRESHOLD_UNUSUAL_HOURS" ]]; then
        local late_logins
        late_logins=$(who | wc -l | tr -d ' ')
        
        if [[ "$late_logins" -gt 0 ]]; then
            alerts+=("Late night login activity detected: $late_logins active sessions after $ALERT_THRESHOLD_UNUSUAL_HOURS:00")
        fi
    fi
    
    # Check for multiple failed login attempts
    local failed_logins
    failed_logins=$(grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | wc -l | tr -d ' ')
    
    if [[ "$failed_logins" -ge "$ALERT_THRESHOLD_FAILED_LOGINS" ]]; then
        alerts+=("High number of failed login attempts today: $failed_logins failures")
    fi
    
    # Check for root logins
    local root_logins
    root_logins=$(last | grep "^root " | head -5 | wc -l | tr -d ' ')
    
    if [[ "$root_logins" -gt 0 ]]; then
        alerts+=("Recent root login activity detected: $root_logins sessions")
    fi
    
    # Check for simultaneous logins from same user
    local duplicate_users
    duplicate_users=$(who | awk '{print $1}' | sort | uniq -d)
    
    if [[ -n "$duplicate_users" ]]; then
        alerts+=("Multiple simultaneous sessions detected for users: $duplicate_users")
    fi
    
    # Report alerts
    if [[ ${#alerts[@]} -eq 0 ]]; then
        log_action "✅ No suspicious login activity detected"
        return 0
    else
        log_action "⚠️  Suspicious login activity alerts:"
        for alert in "${alerts[@]}"; do
            log_action "  - $alert"
        done
        return 1
    fi
}

# Analyze login patterns for security insights
analyze_security_patterns() {
    log_action "Analyzing login patterns for security insights..."
    
    echo "=== Security Pattern Analysis ==="
    echo ""
    
    # Login frequency by day of week
    echo "1. LOGIN FREQUENCY BY DAY:"
    echo "--------------------------"
    last | grep -v "wtmp begins" | awk '{print $4}' | sort | uniq -c | sort -nr
    echo ""
    
    # Most active users
    echo "2. MOST ACTIVE USERS:"
    echo "--------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    echo ""
    
    # Login sources analysis
    echo "3. LOGIN SOURCES:"
    echo "----------------"
    echo "Console logins: $(last | grep -c "console")"
    echo "Remote logins: $(last | grep -v "console" | grep -v "wtmp begins" | wc -l | tr -d ' ')"
    echo ""
    
    # Session duration analysis
    echo "4. SESSION PATTERNS:"
    echo "-------------------"
    local avg_sessions
    avg_sessions=$(last | grep -v "wtmp begins" | grep -v "still logged in" | wc -l | tr -d ' ')
    echo "Total completed sessions: $avg_sessions"
    
    local active_sessions
    active_sessions=$(who | wc -l | tr -d ' ')
    echo "Currently active sessions: $active_sessions"
    echo ""
    
    # Time-based analysis
    echo "5. LOGIN TIME PATTERNS:"
    echo "----------------------"
    echo "Business hours (9-17): $(last | awk '{print $7}' | grep -E '^(09|1[0-7]):' | wc -l | tr -d ' ')"
    echo "After hours (18-08): $(last | awk '{print $7}' | grep -E '^(1[8-9]|2[0-3]|0[0-8]):' | wc -l | tr -d ' ')"
}

# User access audit
perform_user_audit() {
    local audit_file="$REPORT_DIR/user_audit_$(date +%Y%m%d_%H%M%S).txt"
    
    log_action "Performing comprehensive user access audit: $audit_file"
    
    {
        echo "Roundfleet User Access Audit Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "=================================="
        echo ""
        
        echo "SYSTEM OVERVIEW:"
        echo "----------------"
        echo "macOS Version: $(sw_vers -productVersion)"
        echo "Build: $(sw_vers -buildVersion)"
        echo "System Uptime: $(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')"
        echo "Current Date/Time: $(date)"
        echo ""
        
        echo "USER ACCOUNT SUMMARY:"
        echo "---------------------"
        echo "Total system users: $(dscl . list /Users | wc -l | tr -d ' ')"
        echo "Regular users (UID >= 500): $(dscl . list /Users UniqueID | awk '$2 >= 500' | wc -l | tr -d ' ')"
        echo "Currently logged in: $(who | wc -l | tr -d ' ')"
        echo ""
        
        echo "DETAILED USER INFORMATION:"
        echo "--------------------------"
        dscl . list /Users UniqueID | awk '$2 >= 500' | while read -r username uid; do
            echo "User: $username (UID: $uid)"
            
            # Real name
            local real_name
            real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | grep "RealName:" | cut -d' ' -f2-)
            echo "  Real Name: ${real_name:-"Not set"}"
            
            # Home directory
            local home_dir
            home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | grep "NFSHomeDirectory:" | cut -d' ' -f2)
            echo "  Home Directory: ${home_dir:-"Not set"}"
            
            # Last login
            local last_login
            last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $4, $5, $6, $7}')
            echo "  Last Login: ${last_login:-"Never"}"
            
            # Account status
            local account_disabled
            account_disabled=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep -c "DisabledUser" || echo "0")
            if [[ "$account_disabled" -gt 0 ]]; then
                echo "  Status: DISABLED"
            else
                echo "  Status: Active"
            fi
            
            echo ""
        done
        
        echo "RECENT LOGIN ACTIVITY:"
        echo "----------------------"
        last -50
        
        echo ""
        echo "SECURITY RECOMMENDATIONS:"
        echo "-------------------------"
        
        # Check for users without recent login activity
        local inactive_users
        inactive_users=$(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}' | while read -r user; do
            if ! last "$user" | grep -q "$(date '+%b')" 2>/dev/null; then
                echo "$user"
            fi
        done)
        
        if [[ -n "$inactive_users" ]]; then
            echo "• Consider reviewing inactive user accounts:"
            echo "$inactive_users" | while read -r user; do
                echo "  - $user"
            done
        else
            echo "• All users have recent login activity"
        fi
        
        # Check for admin users
        local admin_users
        admin_users=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | cut -d' ' -f2-)
        if [[ -n "$admin_users" ]]; then
            echo "• Review admin user access regularly:"
            for admin in $admin_users; do
                echo "  - $admin"
            done
        fi
        
    } > "$audit_file"
    
    log_action "User access audit completed successfully"
    echo "$audit_file"
}

# Export login data for external analysis
export_login_data() {
    local export_format="${1:-json}"  # json, csv, xml
    local export_file="$REPORT_DIR/login_export_$(date +%Y%m%d_%H%M%S).$export_format"
    
    log_action "Exporting login data in $export_format format: $export_file"
    
    case "$export_format" in
        "csv")
            {
                echo "User,Terminal,Source,LoginDate,LoginTime,LogoutInfo,Duration"
                last -100 | grep -v "wtmp begins" | while IFS= read -r line; do
                    if [[ -n "$line" ]]; then
                        echo "$line" | awk -F' ' '{
                            user=$1; terminal=$2; source=$3; 
                            login_date=$4" "$5" "$6; login_time=$7; 
                            logout_info=$9" "$10; duration=$8;
                            print user","terminal","source","login_date","login_time","logout_info","duration
                        }'
                    fi
                done
            } > "$export_file"
            ;;
        "json")
            generate_login_report > /dev/null
            cp "$REPORT_DIR"/login_report_*.json "$export_file" 2>/dev/null || echo "{\"error\": \"No recent report found\"}" > "$export_file"
            ;;
        "xml")
            {
                echo '<?xml version="1.0" encoding="UTF-8"?>'
                echo '<login_history>'
                echo "  <generated>$(date -u +%Y-%m-%dT%H:%M:%SZ)</generated>"
                echo "  <hostname>$(hostname)</hostname>"
                echo "  <sessions>"
                
                last -50 | grep -v "wtmp begins" | while IFS= read -r line; do
                    if [[ -n "$line" ]]; then
                        local user terminal source login_date login_time
                        user=$(echo "$line" | awk '{print $1}')
                        terminal=$(echo "$line" | awk '{print $2}')
                        source=$(echo "$line" | awk '{print $3}')
                        login_date=$(echo "$line" | awk '{print $4, $5, $6}')
                        login_time=$(echo "$line" | awk '{print $7}')
                        
                        echo "    <session>"
                        echo "      <user>$user</user>"
                        echo "      <terminal>$terminal</terminal>"
                        echo "      <source>$source</source>"
                        echo "      <login_date>$login_date</login_date>"
                        echo "      <login_time>$login_time</login_time>"
                        echo "    </session>"
                    fi
                done
                
                echo "  </sessions>"
                echo '</login_history>'
            } > "$export_file"
            ;;
        *)
            log_action "ERROR: Unsupported export format: $export_format"
            return 1
            ;;
    esac
    
    log_action "Login data exported successfully"
    echo "$export_file"
}

# Main management function
main() {
    local action="${1:-report}"
    local parameter="$2"
    
    setup_directories
    log_action "Roundfleet Login History Management started with action: $action"
    
    case "$action" in
        "brief")
            who
            ;;
        "detailed")
            last
            ;;
        "user")
            if [[ -n "$parameter" ]]; then
                last -1 "$parameter"
            else
                echo "Usage: $0 user <username>"
                exit 1
            fi
            ;;
        "users")
            dscl . list /Users | grep -v "^_"
            ;;
        "analyze")
            analyze_security_patterns
            ;;
        "monitor")
            monitor_suspicious_activity
            ;;
        "audit")
            perform_user_audit
            ;;
        "export")
            export_login_data "$parameter"
            ;;
        "report"|*)
            generate_login_report
            ;;
    esac
    
    log_action "Roundfleet Login History Management completed with action: $action"
}

# Execute main function with all arguments
main "$@"

Quick Management Functions

Simple Login Status Check

#!/bin/bash

# Quick login status with enhanced output
quick_login_status() {
    echo "📊 Roundfleet Login Status - $(date)"
    echo "=================================="
    
    # Current users
    local current_users
    current_users=$(who | wc -l | tr -d ' ')
    echo "👥 Currently logged in: $current_users users"
    
    if [[ "$current_users" -gt 0 ]]; then
        echo ""
        echo "Active Sessions:"
        who | while IFS= read -r line; do
            echo "  🔹 $line"
        done
    fi
    
    echo ""
    echo "📈 Recent Activity:"
    echo "  - Last 24 hours: $(last -t "$(date -v-1d '+%Y%m%d%H%M%S' 2>/dev/null || date -d 'yesterday' '+%Y%m%d%H%M%S')" | wc -l | tr -d ' ') logins"
    echo "  - This week: $(last | grep "$(date '+%b')" | wc -l | tr -d ' ') logins"
    
    # System uptime
    echo "  - System uptime: $(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')"
}

quick_login_status

User Login Summary

#!/bin/bash

# Generate user login summary
user_login_summary() {
    echo "🔍 User Login Summary"
    echo "===================="
    echo ""
    
    echo "Top 10 Most Active Users:"
    echo "------------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10 | while read -r count user; do
        echo "  $user: $count logins"
    done
    
    echo ""
    echo "Recent User Activity:"
    echo "--------------------"
    dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}' | head -10 | while read -r username; do
        local last_login
        last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $4, $5, $7}' | tr -s ' ')
        echo "  $username: ${last_login:-"No recent activity"}"
    done
}

user_login_summary

Security Monitoring Functions

Failed Login Detection

#!/bin/bash

# Monitor and report failed login attempts
monitor_failed_logins() {
    echo "🔒 Failed Login Monitoring"
    echo "=========================="
    echo ""
    
    # Check system log for authentication failures
    echo "Recent Failed Login Attempts:"
    echo "-----------------------------"
    
    # Last 24 hours of failed attempts
    grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | while IFS= read -r line; do
        echo "  ⚠️  $line"
    done || echo "  ✅ No failed login attempts found today"
    
    echo ""
    echo "Failed Login Summary:"
    echo "--------------------"
    
    # Count failures by user (if available)
    local failure_count
    failure_count=$(grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | wc -l | tr -d ' ')
    echo "  Total failures today: $failure_count"
    
    # Recommendations
    if [[ "$failure_count" -gt 5 ]]; then
        echo ""
        echo "🚨 Security Alert: High number of failed logins detected!"
        echo "  - Review user accounts for potential brute force attacks"
        echo "  - Consider implementing account lockout policies"
        echo "  - Check for suspicious IP addresses in logs"
    fi
}

monitor_failed_logins

Session Duration Analysis

#!/bin/bash

# Analyze user session durations
analyze_session_duration() {
    echo "⏱️  Session Duration Analysis"
    echo "============================="
    echo ""
    
    echo "Session Statistics:"
    echo "-------------------"
    
    # Active sessions
    local active_count
    active_count=$(who | wc -l | tr -d ' ')
    echo "  Active sessions: $active_count"
    
    # Completed sessions analysis
    echo "  Recent completed sessions:"
    last | grep -v "still logged in" | grep -v "wtmp begins" | head -10 | while IFS= read -r line; do
        local duration
        duration=$(echo "$line" | awk '{print $10}' | tr -d '()')
        if [[ -n "$duration" ]]; then
            echo "    Duration: $duration"
        fi
    done
    
    echo ""
    echo "Long-running Sessions (Active):"
    echo "-------------------------------"
    who -u | while IFS= read -r line; do
        local login_time pid idle
        login_time=$(echo "$line" | awk '{print $3, $4}')
        pid=$(echo "$line" | awk '{print $6}')
        idle=$(echo "$line" | awk '{print $5}')
        
        if [[ "$idle" != "." ]]; then
            echo "  Session started: $login_time (Idle: $idle)"
        else
            echo "  Session started: $login_time (Active)"
        fi
    done
}

analyze_session_duration

Configuration and Compliance

Login Policy Configuration

# /etc/roundfleet/login_monitoring.conf
# Roundfleet Login History Monitoring Configuration

# Alert thresholds
ALERT_THRESHOLD_FAILED_LOGINS=5
ALERT_THRESHOLD_UNUSUAL_HOURS=22
ALERT_THRESHOLD_SIMULTANEOUS_SESSIONS=3

# Monitoring settings
MONITOR_INTERVAL_MINUTES=15
LOG_RETENTION_DAYS=90
REPORT_GENERATION_SCHEDULE="daily"

# Security policies
REQUIRE_LOGIN_AUDIT_TRAIL=true
ALERT_ON_ROOT_LOGIN=true
ALERT_ON_AFTER_HOURS_LOGIN=true
MONITOR_REMOTE_LOGINS=true

# Compliance settings
GDPR_COMPLIANCE=true
SOX_COMPLIANCE=false
HIPAA_COMPLIANCE=false
EXPORT_FORMAT="json"  # json, csv, xml

Compliance Reporting

#!/bin/bash

# Generate compliance-ready login reports
generate_compliance_report() {
    local compliance_type="${1:-general}"
    local report_file="$REPORT_DIR/compliance_${compliance_type}_$(date +%Y%m%d).txt"
    
    echo "📋 Generating $compliance_type compliance report..."
    
    {
        echo "LOGIN HISTORY COMPLIANCE REPORT"
        echo "==============================="
        echo "Report Type: $compliance_type"
        echo "Generated: $(date)"
        echo "Period: $(date -v-30d '+%Y-%m-%d') to $(date '+%Y-%m-%d')"
        echo "System: $(hostname)"
        echo ""
        
        case "$compliance_type" in
            "gdpr")
                echo "GDPR DATA PROCESSING RECORD:"
                echo "----------------------------"
                echo "• Login data collected for security monitoring"
                echo "• Data retention: 90 days (configurable)"
                echo "• Access controls: Admin users only"
                echo "• Data subjects: All system users"
                echo ""
                ;;
            "sox")
                echo "SOX ACCESS CONTROL COMPLIANCE:"
                echo "------------------------------"
                echo "• User access monitoring: Enabled"
                echo "• Privileged access tracking: Enabled"
                echo "• Failed login monitoring: Enabled"
                echo "• Audit trail completeness: Verified"
                echo ""
                ;;
            "hipaa")
                echo "HIPAA ACCESS AUDIT REQUIREMENTS:"
                echo "--------------------------------"
                echo "• User authentication logging: Active"
                echo "• Access attempt monitoring: Enabled"
                echo "• Minimum necessary access: Under review"
                echo "• Audit log integrity: Maintained"
                echo ""
                ;;
        esac
        
        echo "DETAILED LOGIN ACTIVITY:"
        echo "------------------------"
        last -30
        
        echo ""
        echo "USER ACCESS SUMMARY:"
        echo "-------------------"
        dscl . list /Users UniqueID | awk '$2 >= 500' | while read -r username uid; do
            local login_count
            login_count=$(last "$username" | grep -v "wtmp begins" | wc -l | tr -d ' ')
            echo "$username (UID: $uid): $login_count login sessions"
        done
        
    } > "$report_file"
    
    echo "✅ Compliance report generated: $report_file"
}

# Generate different compliance reports
# generate_compliance_report "gdpr"
# generate_compliance_report "sox"
# generate_compliance_report "hipaa"

Important Technical Notes

Command Details

  • who: Shows current logged-in users with login times
  • last: Displays login history from /var/log/wtmp
  • dscl: Directory Services command line for user information
  • w: Extended version of who with system load information

Log File Locations

  • /var/log/wtmp: Binary login history database
  • /var/log/system.log: System log including authentication events
  • /var/log/secure.log: Security-related log entries (if enabled)

Security Considerations

  1. Privacy Compliance: Login monitoring must comply with local privacy laws
  2. Data Retention: Implement appropriate retention policies for audit logs
  3. Access Control: Restrict access to login history data to authorized personnel
  4. Real-time Monitoring: Consider implementing real-time alerts for suspicious activity

Best Practices

  1. Regular Auditing: Review login patterns regularly for anomalies
  2. Automated Monitoring: Set up automated alerts for suspicious activity
  3. Data Retention: Maintain appropriate log retention for compliance requirements
  4. User Privacy: Balance security monitoring with user privacy expectations
  5. Documentation: Maintain clear documentation of monitoring procedures
  6. Integration: Consider integrating with SIEM systems for centralized monitoring
  7. Performance Impact: Monitor system performance impact of logging activities
  8. Backup Strategy: Implement backup procedures for critical audit logs

Remember to validate all scripts on test devices before deploying across your Roundfleet environment, and ensure compliance with your organization's privacy and security policies when implementing login history monitoring.

Manage Location Services on macOS

Control Location Services across your Roundfleet devices using command-line tools. This tutorial covers enabling, disabling, and monitoring location services for better privacy management and security compliance.

Understanding macOS Location Services

Location Services enable macOS applications and services to gather location-based information to enhance user experience. However, enabling these services can create potential security and privacy concerns.

Key considerations:

  • Enhanced functionality - Apps like Maps require location access
  • Privacy concerns - Potential for tracking and data collection
  • Security risks - Increased attack surface for malicious actors
  • Compliance requirements - Enterprise policies may require location restrictions

Enable Location Services

Basic Location Services Activation

#!/bin/bash

# Enable Location Services system-wide
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

echo "Location Services enabled successfully"
echo "⚠️  Device restart required for changes to take effect"

Enable with Automatic Restart

#!/bin/bash

# Enable Location Services and schedule restart
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

echo "Location Services configuration updated"
echo "Scheduling system restart in 60 seconds..."

# Give users time to save work
sleep 60
sudo reboot

Verify Activation Success

#!/bin/bash

# Enable Location Services with verification
echo "Enabling Location Services..."
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

# Check if the setting was applied
if sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" LocationServicesEnabled 2>/dev/null; then
    echo "✅ Location Services configuration updated successfully"
    echo "🔄 Restart required to apply changes"
else
    echo "❌ Failed to update Location Services configuration"
    exit 1
fi

Disable Location Services

Basic Location Services Deactivation

#!/bin/bash

# Disable Location Services system-wide
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

echo "Location Services disabled successfully"
echo "⚠️  Device restart required for changes to take effect"

Disable with Privacy Notification

#!/bin/bash

# Disable Location Services with user notification
echo "🔒 Implementing privacy protection measures..."
echo "Disabling Location Services for enhanced security"

sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

echo "✅ Location Services have been disabled"
echo "🔄 System restart required to complete the process"
echo "📱 Applications will no longer have access to location data"

Enterprise Security Disable

#!/bin/bash

# Enterprise-grade location services disable with logging
LOG_FILE="/var/log/roundfleet_location_services.log"

# Logging function
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

log_action "=== Location Services Security Disable Initiated ==="

# Check current status
CURRENT_STATUS=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" LocationServicesEnabled 2>/dev/null)

if [[ "$CURRENT_STATUS" == "1" ]]; then
    log_action "Location Services currently enabled - proceeding with disable"
    
    # Disable location services
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false
    
    log_action "Location Services disabled for security compliance"
    log_action "System restart required to complete security hardening"
    
    echo "🔒 Security policy applied: Location Services disabled"
    echo "📋 Action logged to: $LOG_FILE"
else
    log_action "Location Services already disabled - no action required"
    echo "✅ Location Services already secured"
fi

Check Location Services Status

Basic Status Check

#!/bin/bash

# Check current Location Services status
sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd"

echo "Location Services status retrieved"

Detailed Status Report

#!/bin/bash

# Comprehensive Location Services status check
echo "=== Location Services Status Report ==="
echo "Device: $(hostname)"
echo "Date: $(date)"
echo "========================================"

# Check if locationd daemon is running
if pgrep -x "locationd" > /dev/null; then
    echo "📍 Location daemon: Running"
else
    echo "❌ Location daemon: Not running"
fi

# Get current configuration
STATUS_OUTPUT=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" 2>&1)

if echo "$STATUS_OUTPUT" | grep -q "LocationServicesEnabled = 1"; then
    echo "🟢 Location Services: ENABLED"
    echo "📱 Applications can access location data"
elif echo "$STATUS_OUTPUT" | grep -q "LocationServicesEnabled = 0"; then
    echo "🔴 Location Services: DISABLED"
    echo "🔒 Location access blocked for all applications"
else
    echo "⚠️  Location Services: Status unclear"
    echo "Raw output: $STATUS_OUTPUT"
fi

echo "========================================"

Fleet-wide Status Monitoring

#!/bin/bash

# Roundfleet Location Services Monitoring Script
LOG_FILE="/var/log/roundfleet_location_monitoring.log"
REPORT_FILE="/tmp/location_services_report.txt"

# Create status report
generate_report() {
    {
        echo "Roundfleet Location Services Report"
        echo "Generated: $(date)"
        echo "Device: $(hostname)"
        echo "User: $(whoami)"
        echo "================================"
        echo ""
        
        # System information
        echo "System Information:"
        echo "OS Version: $(sw_vers -productVersion)"
        echo "Build: $(sw_vers -buildVersion)"
        echo ""
        
        # Location daemon status
        echo "Location Daemon Status:"
        if pgrep -x "locationd" > /dev/null; then
            echo "Status: Running (PID: $(pgrep -x "locationd"))"
        else
            echo "Status: Not Running"
        fi
        echo ""
        
        # Configuration status
        echo "Location Services Configuration:"
        local status_output
        status_output=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" 2>&1)
        
        if echo "$status_output" | grep -q "LocationServicesEnabled = 1"; then
            echo "Status: ENABLED"
            echo "Privacy Level: Standard"
        elif echo "$status_output" | grep -q "LocationServicesEnabled = 0"; then
            echo "Status: DISABLED"
            echo "Privacy Level: High"
        else
            echo "Status: Unknown"
            echo "Raw Configuration:"
            echo "$status_output"
        fi
        
        echo ""
        echo "Report completed at: $(date)"
        
    } > "$REPORT_FILE"
    
    echo "📊 Report generated: $REPORT_FILE"
}

# Log monitoring action
echo "$(date '+%Y-%m-%d %H:%M:%S') - Location Services monitoring initiated" >> "$LOG_FILE"

# Generate the report
generate_report

# Display summary
echo "=== Roundfleet Location Services Summary ==="
cat "$REPORT_FILE"

Advanced Location Management

Conditional Location Control

#!/bin/bash

# Smart location services management based on environment
NETWORK_SSID=$(networksetup -getairportnetwork en0 | cut -d' ' -f4-)
LOCATION_POLICY=""

# Define location policies based on network
case "$NETWORK_SSID" in
    "Corporate_WiFi"|"Company_Network")
        LOCATION_POLICY="disable"
        echo "🏢 Corporate network detected - applying security policy"
        ;;
    "Home_Network"|"Personal_WiFi")
        LOCATION_POLICY="enable"
        echo "🏠 Personal network detected - allowing location services"
        ;;
    *)
        LOCATION_POLICY="disable"
        echo "🔒 Unknown network - applying restrictive policy"
        ;;
esac

# Apply the policy
if [[ "$LOCATION_POLICY" == "disable" ]]; then
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false
    echo "🔴 Location Services disabled for security"
else
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true
    echo "🟢 Location Services enabled"
fi

echo "⚠️  Restart required for changes to take effect"

Location Services Backup and Restore

#!/bin/bash

# Backup and restore location services configuration
BACKUP_DIR="/var/backups/roundfleet"
BACKUP_FILE="$BACKUP_DIR/location_services_$(date +%Y%m%d_%H%M%S).plist"

# Create backup directory
sudo mkdir -p "$BACKUP_DIR"

backup_settings() {
    echo "📦 Backing up Location Services configuration..."
    
    if sudo cp "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist" "$BACKUP_FILE" 2>/dev/null; then
        echo "✅ Backup saved to: $BACKUP_FILE"
    else
        echo "❌ Backup failed - configuration file may not exist"
        return 1
    fi
}

restore_settings() {
    local restore_file="$1"
    
    if [[ -z "$restore_file" ]]; then
        echo "Usage: restore_settings <backup_file>"
        return 1
    fi
    
    if [[ ! -f "$restore_file" ]]; then
        echo "❌ Backup file not found: $restore_file"
        return 1
    fi
    
    echo "🔄 Restoring Location Services configuration..."
    
    if sudo cp "$restore_file" "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist"; then
        echo "✅ Configuration restored successfully"
        echo "🔄 Restart required to apply changes"
    else
        echo "❌ Restore failed"
        return 1
    fi
}

# Execute backup
backup_settings

Security Considerations

Enterprise Security Hardening

#!/bin/bash

# Comprehensive location services security hardening
echo "🔒 Roundfleet Security Hardening: Location Services"
echo "================================================="

# 1. Disable location services
echo "Step 1: Disabling Location Services..."
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

# 2. Verify daemon configuration
echo "Step 2: Verifying daemon configuration..."
if pgrep -x "locationd" > /dev/null; then
    echo "⚠️  Location daemon still running (will stop after restart)"
else
    echo "✅ Location daemon not running"
fi

# 3. Set file permissions
echo "Step 3: Securing configuration files..."
sudo chmod 600 /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist 2>/dev/null
sudo chown _locationd:_locationd /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist 2>/dev/null

# 4. Create security report
SECURITY_REPORT="/var/log/roundfleet_location_security.log"
{
    echo "Roundfleet Location Security Hardening Report"
    echo "Date: $(date)"
    echo "Device: $(hostname)"
    echo "Action: Location Services Disabled"
    echo "Compliance: Enhanced Privacy Protection"
    echo "Next Steps: System restart required"
} | sudo tee -a "$SECURITY_REPORT"

echo "✅ Security hardening completed"
echo "📋 Report saved to: $SECURITY_REPORT"
echo "🔄 System restart required to complete hardening"

Important Notes

  • System restart required - Changes take effect only after reboot
  • Administrative privileges - All commands require sudo access
  • App-specific settings - These scripts control system-wide settings only
  • macOS version compatibility - Scripts tested on macOS 10.14+
  • Privacy compliance - Consider legal requirements in your jurisdiction
  • User notification - Inform users of location policy changes

Troubleshooting

Common Issues

Permission Denied:

# Ensure proper daemon user context
sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd"

Configuration Not Applied:

# Force restart location daemon
sudo launchctl unload /System/Library/LaunchDaemons/com.apple.locationd.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.locationd.plist

Verification Issues:

# Check system integrity
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate

Remember to test these scripts on individual devices before deploying across your Roundfleet environment.