Tutorial

New updates and improvements to Roundfleet.

Firewall Management for macOS

Implement enterprise-grade firewall management across your Roundfleet deployment with automated security policies, advanced network protection, threat detection, and comprehensive compliance monitoring. This tutorial provides solutions for maintaining robust network security while ensuring regulatory compliance and operational efficiency.

Understanding macOS Firewall Management

macOS provides several firewall management tools and mechanisms:

  • Application Firewall - Built-in firewall that blocks incoming connections
  • socketfilterfw - Command-line tool for firewall configuration
  • pfctl - Packet Filter control utility (advanced filtering)
  • System Preferences - GUI firewall management interface
  • Configuration Profiles - MDM-based firewall policy deployment

Basic Firewall Operations

Enable Firewall

#!/bin/bash

# Enable macOS firewall
sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1

Disable Firewall

#!/bin/bash

# Disable macOS firewall
sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 0

Check Firewall Status

#!/bin/bash

# Check firewall status
/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate

Enterprise Firewall Management System

Comprehensive Firewall Management Tool

#!/bin/bash

# Roundfleet Enterprise Firewall Management Tool
# Advanced network security and compliance monitoring

# Configuration
CONFIG_FILE="/etc/roundfleet/firewall_policy.conf"
LOG_FILE="/var/log/roundfleet_firewall.log"
RULES_DIR="/Library/Roundfleet/FirewallRules"
AUDIT_LOG="/var/log/roundfleet_firewall_audit.log"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$RULES_DIR" "$(dirname "$AUDIT_LOG")"

# Default firewall policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Enterprise Firewall Management Policy
# Version: 2.0

# Firewall Enforcement Settings
ENFORCE_FIREWALL_ENABLED=true
AUTO_ENABLE_ON_VIOLATION=true
BLOCK_ALL_INCOMING_DEFAULT=true
ALLOW_SIGNED_APPS=true
STEALTH_MODE_ENABLED=true

# Application Control
WHITELIST_SYSTEM_APPS=true
REQUIRE_APP_SIGNATURES=true
BLOCK_UNSIGNED_APPS=true
LOG_ALL_CONNECTIONS=true
AUTO_BLOCK_SUSPICIOUS_APPS=true

# Network Security Policies
BLOCK_PRIVATE_NETWORKS=false
ALLOW_APPLE_SERVICES=true
BLOCK_P2P_CONNECTIONS=true
MONITOR_OUTBOUND_CONNECTIONS=true
RATE_LIMIT_CONNECTIONS=true

# Advanced Security Features
INTRUSION_DETECTION=true
THREAT_INTELLIGENCE_ENABLED=true
GEO_BLOCKING_ENABLED=false
DLP_INSPECTION=true
MALWARE_DETECTION=true

# Compliance and Monitoring
COMPLIANCE_MONITORING=true
SECURITY_BASELINE_ENFORCEMENT=true
AUTOMATED_REPORTING=true
REAL_TIME_ALERTS=true
INCIDENT_RESPONSE=true

# Policy Templates
DEFAULT_SECURITY_PROFILE="corporate_high"
ALLOWED_PORTS="22,53,80,443,993,995"
BLOCKED_COUNTRIES=""
WHITELIST_DOMAINS="*.apple.com,*.icloud.com"

# Maintenance Settings
AUTO_UPDATE_RULES=true
BACKUP_CONFIGURATIONS=true
LOG_RETENTION_DAYS=90
PERFORMANCE_MONITORING=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"
}

# Audit logging function
audit_log() {
    local action="$1"
    local result="$2"
    local details="$3"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - ACTION:$action RESULT:$result DETAILS:$details USER:$(whoami)" >> "$AUDIT_LOG"
}

# Get current firewall status
get_firewall_status() {
    echo "=== Current Firewall Status ==="
    
    # Check global firewall state
    local global_state
    global_state=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null | grep -o "enabled\|disabled")
    
    echo "Global Firewall State: $global_state"
    
    # Check stealth mode
    local stealth_mode
    stealth_mode=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 2>/dev/null | grep -o "enabled\|disabled")
    
    echo "Stealth Mode: $stealth_mode"
    
    # Check logging state
    local logging_state
    logging_state=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getloggingmode 2>/dev/null | grep -o "enabled\|disabled")
    
    echo "Logging: $logging_state"
    
    # Check block all mode
    local block_all
    block_all=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getblockall 2>/dev/null | grep -o "enabled\|disabled")
    
    echo "Block All Incoming: $block_all"
    
    # Check allowed applications
    echo -e "\nAllowed Applications:"
    /usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | grep "ALF" | head -10
    
    return 0
}

# Enable firewall with enterprise settings
enterprise_firewall_enable() {
    local security_profile="${1:-$DEFAULT_SECURITY_PROFILE}"
    
    echo "=== Enabling Enterprise Firewall ==="
    echo "Security Profile: $security_profile"
    
    # Enable global firewall
    log_action "Enabling global firewall"
    if sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 1; then
        echo "✅ Global firewall enabled"
        audit_log "FIREWALL_ENABLE" "SUCCESS" "Global firewall activated"
    else
        echo "❌ Failed to enable global firewall"
        audit_log "FIREWALL_ENABLE" "FAILED" "Global firewall activation failed"
        return 1
    fi
    
    # Configure based on security profile
    case "$security_profile" in
        "corporate_high")
            configure_high_security_profile
            ;;
        "corporate_standard")
            configure_standard_security_profile
            ;;
        "developer")
            configure_developer_profile
            ;;
        "kiosk")
            configure_kiosk_profile
            ;;
        *)
            echo "Unknown security profile, using standard configuration"
            configure_standard_security_profile
            ;;
    esac
    
    # Enable stealth mode if required
    if [[ "$STEALTH_MODE_ENABLED" == "true" ]]; then
        enable_stealth_mode
    fi
    
    # Enable logging if required
    if [[ "$LOG_ALL_CONNECTIONS" == "true" ]]; then
        enable_firewall_logging
    fi
    
    # Apply application rules
    configure_application_rules
    
    echo "✅ Enterprise firewall configuration completed"
    log_action "Enterprise firewall enabled with profile: $security_profile"
    
    return 0
}

# Configure high security profile
configure_high_security_profile() {
    echo "=== Configuring High Security Profile ==="
    
    # Block all incoming connections by default
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall on 2>/dev/null
    
    # Enable stealth mode
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on 2>/dev/null
    
    # Disable automatic allow for signed apps
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned off 2>/dev/null
    
    # Block all unsigned applications
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsignedapp off 2>/dev/null
    
    echo "High security profile configured"
    log_action "High security firewall profile applied"
}

# Configure standard security profile
configure_standard_security_profile() {
    echo "=== Configuring Standard Security Profile ==="
    
    # Allow essential incoming connections
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall off 2>/dev/null
    
    # Enable stealth mode
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on 2>/dev/null
    
    # Allow signed applications
    if [[ "$ALLOW_SIGNED_APPS" == "true" ]]; then
        sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned on 2>/dev/null
    fi
    
    echo "Standard security profile configured"
    log_action "Standard security firewall profile applied"
}

# Configure developer profile
configure_developer_profile() {
    echo "=== Configuring Developer Profile ==="
    
    # Allow more permissive settings for development
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall off 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode off 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned on 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsignedapp on 2>/dev/null
    
    # Add common development tools
    local dev_apps=(
        "/Applications/Xcode.app"
        "/Applications/Visual Studio Code.app"
        "/Applications/Docker.app"
        "/usr/bin/ssh"
        "/usr/bin/python3"
    )
    
    for app in "${dev_apps[@]}"; do
        if [[ -e "$app" ]]; then
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app" 2>/dev/null
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblock "$app" 2>/dev/null
        fi
    done
    
    echo "Developer profile configured"
    log_action "Developer firewall profile applied"
}

# Configure kiosk profile
configure_kiosk_profile() {
    echo "=== Configuring Kiosk Profile ==="
    
    # Maximum security for kiosk devices
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall on 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsigned off 2>/dev/null
    sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setallowsignedapp off 2>/dev/null
    
    # Only allow essential system applications
    local kiosk_apps=(
        "/System/Library/CoreServices/Finder.app"
        "/Applications/Safari.app"
    )
    
    for app in "${kiosk_apps[@]}"; do
        if [[ -e "$app" ]]; then
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app" 2>/dev/null
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblock "$app" 2>/dev/null
        fi
    done
    
    echo "Kiosk profile configured"
    log_action "Kiosk firewall profile applied"
}

# Enable stealth mode
enable_stealth_mode() {
    echo "=== Enabling Stealth Mode ==="
    
    if sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on 2>/dev/null; then
        echo "✅ Stealth mode enabled"
        log_action "Stealth mode enabled"
        audit_log "STEALTH_MODE" "ENABLED" "Device hidden from network scans"
    else
        echo "❌ Failed to enable stealth mode"
        log_action "FAILED: Stealth mode enable"
    fi
}

# Enable firewall logging
enable_firewall_logging() {
    echo "=== Enabling Firewall Logging ==="
    
    if sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode on 2>/dev/null; then
        echo "✅ Firewall logging enabled"
        log_action "Firewall logging enabled"
        audit_log "LOGGING" "ENABLED" "All firewall events will be logged"
    else
        echo "❌ Failed to enable firewall logging"
        log_action "FAILED: Firewall logging enable"
    fi
}

# Configure application rules
configure_application_rules() {
    echo "=== Configuring Application Rules ==="
    
    # Essential system applications
    local essential_apps=(
        "/System/Library/CoreServices/Software Update.app"
        "/usr/sbin/sshd"
        "/usr/bin/ssh"
        "/Applications/App Store.app"
    )
    
    # Add and allow essential applications
    for app in "${essential_apps[@]}"; do
        if [[ -e "$app" ]]; then
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app" 2>/dev/null
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblock "$app" 2>/dev/null
            echo "✅ Allowed: $(basename "$app")"
        fi
    done
    
    # Block known problematic applications
    local blocked_apps=(
        "/Applications/BitTorrent.app"
        "/Applications/P2P Client.app"
    )
    
    for app in "${blocked_apps[@]}"; do
        if [[ -e "$app" ]]; then
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app" 2>/dev/null
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --block "$app" 2>/dev/null
            echo "🚫 Blocked: $(basename "$app")"
        fi
    done
    
    log_action "Application firewall rules configured"
}

# Disable firewall (with safety checks)
enterprise_firewall_disable() {
    local force="${1:-false}"
    local reason="$2"
    
    echo "=== Disabling Enterprise Firewall ==="
    
    if [[ "$force" != "true" ]]; then
        echo "⚠️  WARNING: Disabling firewall will reduce security"
        echo "Use 'force' parameter to override this warning"
        
        if [[ -z "$reason" ]]; then
            echo "❌ Reason required for firewall disable operation"
            return 1
        fi
    fi
    
    # Log the disable action
    log_action "SECURITY WARNING: Firewall being disabled - Reason: ${reason:-Manual override}"
    audit_log "FIREWALL_DISABLE" "INITIATED" "Reason: ${reason:-Manual override}"
    
    # Disable global firewall
    if sudo defaults write /Library/Preferences/com.apple.alf globalstate -int 0; then
        echo "✅ Global firewall disabled"
        audit_log "FIREWALL_DISABLE" "SUCCESS" "Global firewall deactivated"
        
        # Schedule re-enable if temporary
        if [[ "$reason" == *"temporary"* || "$reason" == *"maintenance"* ]]; then
            schedule_firewall_renable
        fi
        
        return 0
    else
        echo "❌ Failed to disable global firewall"
        audit_log "FIREWALL_DISABLE" "FAILED" "Global firewall deactivation failed"
        return 1
    fi
}

# Schedule firewall re-enable
schedule_firewall_renable() {
    local renable_minutes="${1:-60}"  # Default 1 hour
    
    echo "🕒 Firewall will be automatically re-enabled in $renable_minutes minutes"
    
    # Create background job to re-enable firewall
    (
        sleep $((renable_minutes * 60))
        log_action "Auto re-enabling firewall after maintenance window"
        enterprise_firewall_enable "corporate_standard"
    ) &
    
    local job_pid=$!
    echo "$job_pid" > "/tmp/roundfleet_firewall_renable.pid"
    log_action "Firewall re-enable scheduled for $renable_minutes minutes (PID: $job_pid)"
}

# Check firewall compliance
check_firewall_compliance() {
    echo "=== Firewall Compliance Check ==="
    
    local compliance_issues=()
    local compliance_score=100
    
    # Check if firewall is enabled
    local firewall_state
    firewall_state=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null | grep -o "enabled\|disabled")
    
    if [[ "$firewall_state" != "enabled" ]]; then
        compliance_issues+=("Firewall not enabled")
        compliance_score=$((compliance_score - 30))
    fi
    
    # Check stealth mode
    if [[ "$STEALTH_MODE_ENABLED" == "true" ]]; then
        local stealth_state
        stealth_state=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 2>/dev/null | grep -o "enabled\|disabled")
        
        if [[ "$stealth_state" != "enabled" ]]; then
            compliance_issues+=("Stealth mode not enabled")
            compliance_score=$((compliance_score - 15))
        fi
    fi
    
    # Check logging
    if [[ "$LOG_ALL_CONNECTIONS" == "true" ]]; then
        local logging_state
        logging_state=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getloggingmode 2>/dev/null | grep -o "enabled\|disabled")
        
        if [[ "$logging_state" != "enabled" ]]; then
            compliance_issues+=("Firewall logging not enabled")
            compliance_score=$((compliance_score - 10))
        fi
    fi
    
    # Check for unauthorized applications
    local unauthorized_apps
    unauthorized_apps=$(/usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | grep -i "torrent\|p2p\|limewire" | wc -l)
    
    if [[ $unauthorized_apps -gt 0 ]]; then
        compliance_issues+=("Unauthorized applications detected: $unauthorized_apps")
        compliance_score=$((compliance_score - 20))
    fi
    
    # Report compliance status
    echo "Compliance Score: $compliance_score/100"
    
    if [[ ${#compliance_issues[@]} -eq 0 ]]; then
        echo "✅ Firewall configuration is compliant"
        audit_log "COMPLIANCE_CHECK" "PASSED" "Score: $compliance_score/100"
        return 0
    else
        echo "❌ Compliance issues found:"
        printf '  - %s\n' "${compliance_issues[@]}"
        audit_log "COMPLIANCE_CHECK" "FAILED" "Issues: ${#compliance_issues[@]} Score: $compliance_score/100"
        
        # Auto-remediate if enabled
        if [[ "$AUTO_ENABLE_ON_VIOLATION" == "true" ]]; then
            echo "🔧 Auto-remediation enabled, fixing issues..."
            enterprise_firewall_enable "$DEFAULT_SECURITY_PROFILE"
        fi
        
        return 1
    fi
}

# Monitor firewall events
monitor_firewall_events() {
    echo "=== Starting Firewall Event Monitoring ==="
    
    local log_file="/var/log/appfirewall.log"
    
    if [[ ! -f "$log_file" ]]; then
        echo "⚠️  Firewall log file not found. Enabling logging..."
        enable_firewall_logging
        sleep 2
    fi
    
    echo "Monitoring firewall events... Press Ctrl+C to stop"
    
    # Monitor firewall log in real-time
    tail -f "$log_file" 2>/dev/null | while read -r line; do
        if echo "$line" | grep -q "Deny\|Block"; then
            local app_name
            app_name=$(echo "$line" | awk '{print $8}' | cut -d'(' -f1)
            local action
            action=$(echo "$line" | awk '{print $6}')
            
            echo "🚫 $(date '+%H:%M:%S') - BLOCKED: $app_name ($action)"
            
            # Log security event
            log_action "SECURITY EVENT: $action - Application: $app_name"
            audit_log "FIREWALL_BLOCK" "DETECTED" "App: $app_name Action: $action"
            
            # Check for potential threats
            if echo "$app_name" | grep -i -E "(torrent|p2p|hack|crack|keygen)"; then
                echo "🚨 SECURITY ALERT: Potentially malicious application blocked: $app_name"
                log_action "SECURITY ALERT: Malicious app blocked - $app_name"
            fi
        fi
    done
}

# Generate firewall security report
generate_firewall_report() {
    local report_file="$RULES_DIR/firewall_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Firewall Security Report ==="
    
    # Get current firewall status
    local firewall_enabled="false"
    local stealth_enabled="false"
    local logging_enabled="false"
    local block_all_enabled="false"
    
    if /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null | grep -q "enabled"; then
        firewall_enabled="true"
    fi
    
    if /usr/libexec/ApplicationFirewall/socketfilterfw --getstealthmode 2>/dev/null | grep -q "enabled"; then
        stealth_enabled="true"
    fi
    
    if /usr/libexec/ApplicationFirewall/socketfilterfw --getloggingmode 2>/dev/null | grep -q "enabled"; then
        logging_enabled="true"
    fi
    
    if /usr/libexec/ApplicationFirewall/socketfilterfw --getblockall 2>/dev/null | grep -q "enabled"; then
        block_all_enabled="true"
    fi
    
    # Count allowed/blocked applications
    local total_apps=0
    local allowed_apps=0
    local blocked_apps=0
    
    if command -v /usr/libexec/ApplicationFirewall/socketfilterfw >/dev/null; then
        total_apps=$(/usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | grep -c "ALF" || echo 0)
        allowed_apps=$(/usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | grep -c "ALLOW" || echo 0)
        blocked_apps=$(/usr/libexec/ApplicationFirewall/socketfilterfw --listapps 2>/dev/null | grep -c "BLOCK" || echo 0)
    fi
    
    # Analyze recent security events
    local security_events=0
    local blocked_connections=0
    
    if [[ -f "/var/log/appfirewall.log" ]]; then
        security_events=$(grep -c "$(date '+%Y-%m-%d')" "/var/log/appfirewall.log" 2>/dev/null || echo 0)
        blocked_connections=$(grep -c "Deny\|Block" "/var/log/appfirewall.log" 2>/dev/null || echo 0)
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "firewall_security",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "os_version": "$(sw_vers -productVersion)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
  },
  "firewall_status": {
    "global_firewall_enabled": $firewall_enabled,
    "stealth_mode_enabled": $stealth_enabled,
    "logging_enabled": $logging_enabled,
    "block_all_incoming": $block_all_enabled
  },
  "application_rules": {
    "total_applications": $total_apps,
    "allowed_applications": $allowed_apps,
    "blocked_applications": $blocked_apps
  },
  "security_events": {
    "total_events_today": $security_events,
    "blocked_connections": $blocked_connections,
    "last_event": "$(tail -1 /var/log/appfirewall.log 2>/dev/null | awk '{print $1 " " $2 " " $3}' || echo 'N/A')"
  },
  "compliance_status": {
    "policy_compliant": $(check_firewall_compliance >/dev/null 2>&1 && echo true || echo false),
    "security_profile": "$DEFAULT_SECURITY_PROFILE",
    "auto_remediation": $AUTO_ENABLE_ON_VIOLATION
  },
  "recommendations": [
    $([ "$firewall_enabled" != "true" ] && echo '"Enable global firewall",' || echo "")
    $([ "$stealth_enabled" != "true" ] && echo '"Enable stealth mode",' || echo "")
    $([ "$logging_enabled" != "true" ] && echo '"Enable firewall logging",' || echo "")
    "Regular firewall rule review"
  ]
}
EOF
    
    echo "Firewall security report saved to: $report_file"
    log_action "Firewall security report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Firewall Management Tool Started ==="
    
    case "${1:-status}" in
        "enable")
            enterprise_firewall_enable "$2"
            ;;
        "disable")
            enterprise_firewall_disable "$2" "$3"
            ;;
        "status")
            get_firewall_status
            ;;
        "compliance")
            check_firewall_compliance
            ;;
        "monitor")
            monitor_firewall_events
            ;;
        "report")
            generate_firewall_report
            ;;
        "stealth")
            enable_stealth_mode
            ;;
        "logging")
            enable_firewall_logging
            ;;
        "profile")
            enterprise_firewall_enable "$2"
            ;;
        *)
            echo "Roundfleet Enterprise Firewall Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  enable [profile]              - Enable firewall with security profile"
            echo "  disable [force] [reason]      - Disable firewall (requires reason)"
            echo "  status                        - Show current firewall status"
            echo "  compliance                    - Check firewall compliance"
            echo "  monitor                       - Monitor firewall events in real-time"
            echo "  report                        - Generate security report"
            echo "  stealth                       - Enable stealth mode"
            echo "  logging                       - Enable firewall logging"
            echo "  profile [name]                - Apply specific security profile"
            echo ""
            echo "Security Profiles:"
            echo "  corporate_high                - Maximum security for sensitive environments"
            echo "  corporate_standard            - Standard corporate security (default)"
            echo "  developer                     - Development-friendly settings"
            echo "  kiosk                         - Kiosk/public access security"
            ;;
    esac
    
    log_action "=== Firewall management operation completed ==="
}

# Execute main function
main "$@"

Advanced Firewall Management

Custom Firewall Rules Engine

#!/bin/bash

# Advanced firewall rules management
manage_custom_rules() {
    local action="$1"
    local rule_name="$2"
    local rule_definition="$3"
    
    echo "=== Custom Firewall Rules Management ==="
    
    local rules_file="$RULES_DIR/custom_rules.conf"
    
    case "$action" in
        "add")
            if [[ -z "$rule_name" || -z "$rule_definition" ]]; then
                echo "❌ Rule name and definition required"
                return 1
            fi
            
            # Add rule to configuration
            echo "$rule_name:$rule_definition" >> "$rules_file"
            echo "✅ Custom rule '$rule_name' added"
            log_action "Custom firewall rule added: $rule_name"
            
            # Apply rule immediately
            apply_custom_rule "$rule_definition"
            ;;
        "remove")
            if [[ -f "$rules_file" && -n "$rule_name" ]]; then
                grep -v "^$rule_name:" "$rules_file" > "$rules_file.tmp"
                mv "$rules_file.tmp" "$rules_file"
                echo "✅ Custom rule '$rule_name' removed"
                log_action "Custom firewall rule removed: $rule_name"
            else
                echo "❌ Rule '$rule_name' not found"
            fi
            ;;
        "list")
            if [[ -f "$rules_file" ]]; then
                echo "Custom firewall rules:"
                cat "$rules_file" | while IFS=':' read -r name definition; do
                    echo "  $name: $definition"
                done
            else
                echo "No custom rules configured"
            fi
            ;;
        "apply")
            apply_all_custom_rules
            ;;
        *)
            echo "Usage: manage_custom_rules [add|remove|list|apply] [rule_name] [definition]"
            ;;
    esac
}

# Apply custom firewall rule
apply_custom_rule() {
    local rule_definition="$1"
    
    # Parse rule definition and apply appropriate firewall command
    if echo "$rule_definition" | grep -q "block_app:"; then
        local app_path
        app_path=$(echo "$rule_definition" | cut -d':' -f2)
        sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app_path" 2>/dev/null
        sudo /usr/libexec/ApplicationFirewall/socketfilterfw --block "$app_path" 2>/dev/null
        echo "Applied block rule for: $app_path"
    elif echo "$rule_definition" | grep -q "allow_app:"; then
        local app_path
        app_path=$(echo "$rule_definition" | cut -d':' -f2)
        sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add "$app_path" 2>/dev/null
        sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblock "$app_path" 2>/dev/null
        echo "Applied allow rule for: $app_path"
    fi
}

# Apply all custom rules
apply_all_custom_rules() {
    local rules_file="$RULES_DIR/custom_rules.conf"
    
    if [[ -f "$rules_file" ]]; then
        echo "Applying all custom firewall rules..."
        while IFS=':' read -r name definition; do
            if [[ -n "$name" && -n "$definition" ]]; then
                apply_custom_rule "$definition"
            fi
        done < "$rules_file"
        echo "✅ All custom rules applied"
    else
        echo "No custom rules to apply"
    fi
}

# Example custom rules
create_example_rules() {
    manage_custom_rules "add" "block_bittorrent" "block_app:/Applications/BitTorrent.app"
    manage_custom_rules "add" "allow_docker" "allow_app:/Applications/Docker.app"
    manage_custom_rules "add" "allow_ssh" "allow_app:/usr/bin/ssh"
}

create_example_rules

Network Threat Detection

#!/bin/bash

# Advanced threat detection for firewall
detect_network_threats() {
    echo "=== Network Threat Detection ==="
    
    local threat_indicators=()
    local risk_score=0
    
    # Check for suspicious network connections
    echo "Scanning for suspicious network activity..."
    
    # Check for unusual outbound connections
    local unusual_connections
    unusual_connections=$(netstat -an | grep ESTABLISHED | grep -E ":(6667|6697|1337|31337|4444)" | wc -l)
    
    if [[ $unusual_connections -gt 0 ]]; then
        threat_indicators+=("Suspicious outbound connections detected: $unusual_connections")
        risk_score=$((risk_score + 20))
    fi
    
    # Check for high-risk processes with network access
    local risky_processes=()
    while IFS= read -r line; do
        if echo "$line" | grep -i -E "(torrent|p2p|hack|crack|keygen|bot|trojan)"; then
            risky_processes+=("$line")
            risk_score=$((risk_score + 15))
        fi
    done < <(lsof -i -n | awk '{print $1}' | sort -u)
    
    if [[ ${#risky_processes[@]} -gt 0 ]]; then
        threat_indicators+=("High-risk processes with network access: ${#risky_processes[@]}")
    fi
    
    # Check for firewall bypass attempts
    local bypass_attempts
    bypass_attempts=$(grep -c "socketfilterfw" /var/log/system.log 2>/dev/null || echo 0)
    
    if [[ $bypass_attempts -gt 10 ]]; then
        threat_indicators+=("Potential firewall bypass attempts: $bypass_attempts")
        risk_score=$((risk_score + 25))
    fi
    
    # Report threat assessment
    echo "Threat Risk Score: $risk_score/100"
    
    if [[ ${#threat_indicators[@]} -eq 0 ]]; then
        echo "✅ No immediate threats detected"
        audit_log "THREAT_SCAN" "CLEAN" "Risk score: $risk_score"
        return 0
    else
        echo "⚠️  Potential threats detected:"
        printf '  - %s\n' "${threat_indicators[@]}"
        
        # Log security alert
        log_action "SECURITY ALERT: Network threats detected - Risk score: $risk_score"
        audit_log "THREAT_SCAN" "THREATS_FOUND" "Count: ${#threat_indicators[@]} Risk: $risk_score"
        
        # Auto-remediation for high-risk scenarios
        if [[ $risk_score -gt 50 ]]; then
            echo "🚨 High risk detected - Enabling maximum security profile"
            configure_high_security_profile
        fi
        
        return 1
    fi
}

# Automated threat response
automated_threat_response() {
    local threat_level="$1"
    local threat_type="$2"
    
    echo "=== Automated Threat Response ==="
    echo "Threat Level: $threat_level"
    echo "Threat Type: $threat_type"
    
    case "$threat_level" in
        "high")
            # Maximum security measures
            echo "Implementing high-security measures..."
            sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setblockall on 2>/dev/null
            enable_stealth_mode
            log_action "HIGH THREAT RESPONSE: Maximum security enabled"
            ;;
        "medium")
            # Enhanced monitoring
            echo "Enabling enhanced monitoring..."
            enable_firewall_logging
            log_action "MEDIUM THREAT RESPONSE: Enhanced monitoring enabled"
            ;;
        "low")
            # Standard monitoring
            echo "Maintaining standard security posture..."
            log_action "LOW THREAT RESPONSE: Standard monitoring maintained"
            ;;
        *)
            echo "Unknown threat level: $threat_level"
            ;;
    esac
    
    # Send alert if configured
    if [[ "$REAL_TIME_ALERTS" == "true" ]]; then
        send_security_alert "$threat_level" "$threat_type"
    fi
}

# Send security alert
send_security_alert() {
    local threat_level="$1"
    local threat_type="$2"
    
    local alert_message="SECURITY ALERT: $threat_level level $threat_type detected on $(hostname) at $(date)"
    
    # Log the alert
    log_action "SECURITY ALERT SENT: $alert_message"
    
    # In a real implementation, this would send alerts via:
    # - Email to security team
    # - SIEM integration
    # - Slack/Teams notification
    # - MDM console alert
    
    echo "🚨 Security alert sent: $alert_message"
}

# Example usage:
# detect_network_threats
# automated_threat_response "high" "malware_communication"

Monitoring and Compliance

Real-time Security Monitoring

#!/bin/bash

# Comprehensive firewall security monitoring
start_security_monitoring() {
    echo "=== Starting Real-time Security Monitoring ==="
    
    local monitor_pid_file="$RULES_DIR/security_monitor.pid"
    
    # Store monitor PID
    echo $$ > "$monitor_pid_file"
    
    echo "Security monitoring started (PID: $$)"
    
    # Cleanup function
    cleanup() {
        echo "Stopping security monitor..."
        rm -f "$monitor_pid_file"
        exit 0
    }
    
    trap cleanup SIGTERM SIGINT
    
    while true; do
        # Check firewall compliance every 5 minutes
        if ! check_firewall_compliance >/dev/null 2>&1; then
            echo "⚠️  Compliance violation detected at $(date)"
            
            if [[ "$AUTO_ENABLE_ON_VIOLATION" == "true" ]]; then
                echo "🔧 Auto-remediation triggered"
                enterprise_firewall_enable "$DEFAULT_SECURITY_PROFILE" >/dev/null 2>&1
            fi
        fi
        
        # Run threat detection every 10 minutes
        if [[ $(($(date +%s) % 600)) -eq 0 ]]; then
            detect_network_threats >/dev/null 2>&1
        fi
        
        # Check for firewall configuration changes
        local current_config_hash
        current_config_hash=$(md5 -q /Library/Preferences/com.apple.alf.plist 2>/dev/null || echo "")
        
        if [[ -f "$RULES_DIR/last_config_hash" ]]; then
            local last_hash
            last_hash=$(cat "$RULES_DIR/last_config_hash")
            
            if [[ "$current_config_hash" != "$last_hash" ]]; then
                echo "🔄 Firewall configuration changed at $(date)"
                log_action "Firewall configuration change detected"
                audit_log "CONFIG_CHANGE" "DETECTED" "Hash changed from $last_hash to $current_config_hash"
            fi
        fi
        
        echo "$current_config_hash" > "$RULES_DIR/last_config_hash"
        
        sleep 60  # Check every minute
    done
}

# Stop security monitoring
stop_security_monitoring() {
    local monitor_pid_file="$RULES_DIR/security_monitor.pid"
    
    if [[ -f "$monitor_pid_file" ]]; then
        local monitor_pid
        monitor_pid=$(cat "$monitor_pid_file")
        
        if kill -0 "$monitor_pid" 2>/dev/null; then
            kill "$monitor_pid"
            echo "Security monitor stopped (PID: $monitor_pid)"
            rm -f "$monitor_pid_file"
        else
            echo "Monitor process not found"
            rm -f "$monitor_pid_file"
        fi
    else
        echo "No monitor PID file found"
    fi
}

# Example usage:
# start_security_monitoring &
# stop_security_monitoring

Important Configuration Notes

macOS Firewall Architecture

  • Application Firewall - Controls incoming connections per application
  • Socket Filter Framework - Low-level packet filtering
  • Network Extension Framework - Modern content filtering
  • System Integrity Protection - Protects firewall configuration
  • Privacy Controls - User consent for network access

Enterprise Integration Points

  • MDM Configuration Profiles - Deploy firewall policies centrally
  • SIEM Integration - Forward security logs to monitoring systems
  • Compliance Frameworks - Support for SOC 2, ISO 27001, NIST
  • Incident Response - Automated threat detection and response

Best Practices for Enterprise

  1. Layered Security Approach

    • Combine application firewall with network segmentation
    • Implement endpoint detection and response (EDR)
    • Use network access control (NAC)
    • Deploy intrusion detection systems (IDS)
  2. Policy Management

    • Define clear security baselines
    • Regularly review and update firewall rules
    • Implement change management processes
    • Test security policies regularly
  3. Monitoring and Response

    • Enable comprehensive logging
    • Monitor for configuration changes
    • Implement automated threat detection
    • Establish incident response procedures
  4. Compliance and Auditing

    • Generate regular compliance reports
    • Maintain audit trails
    • Document security exceptions
    • Conduct periodic security assessments

Troubleshooting Common Issues

  • Permission errors - Ensure admin privileges for firewall modifications
  • Application connectivity - Review firewall rules for blocked applications
  • Performance impact - Monitor CPU usage with extensive logging enabled
  • Configuration conflicts - Check for conflicting MDM profiles
  • Log file growth - Implement log rotation and archival

Remember to test firewall configurations thoroughly in a controlled environment before deploying across your entire Roundfleet to ensure business continuity while maintaining security.

Finder Customization Management on macOS

Customize and manage Finder preferences across your Roundfleet devices using command-line tools. This tutorial covers desktop display options, file visibility settings, interface customization, and enterprise-wide Finder configuration management.

Understanding macOS Finder Customization

Finder is the default file manager for macOS, and its behavior can be extensively customized using the defaults command. Key areas of customization include:

  • Desktop Display - Control what appears on desktop
  • File Visibility - Show/hide files and extensions
  • Interface Elements - Status bars, path displays, and warnings
  • Sorting Behavior - How files and folders are organized

Desktop Display Management

Show Hard Disks on Desktop

#!/bin/bash

# Enable hard disk display on desktop
echo "🖥️ Enabling hard disk display on desktop..."

defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Hard disks will now appear on desktop"
else
    echo "❌ Failed to update hard disk display setting"
    exit 1
fi

Show External Hard Drives on Desktop

#!/bin/bash

# Enable external drive display on desktop
echo "💾 Enabling external drive display on desktop..."

defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ External drives will now appear on desktop"
else
    echo "❌ Failed to update external drive display setting"
    exit 1
fi

Show Removable Media on Desktop

#!/bin/bash

# Enable removable media display on desktop
echo "💿 Enabling removable media display on desktop..."

defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Removable media (CDs, DVDs, iPods) will now appear on desktop"
else
    echo "❌ Failed to update removable media display setting"
    exit 1
fi

File Visibility Configuration

Show All Filename Extensions

#!/bin/bash

# Enable display of all file extensions
echo "📄 Enabling display of all file extensions..."

defaults write NSGlobalDomain AppleShowAllExtensions -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ All file extensions will now be visible"
    echo "ℹ️  Files like 'document.txt' and 'app.app' will show their extensions"
else
    echo "❌ Failed to update file extension display setting"
    exit 1
fi

Show Hidden Files

#!/bin/bash

# Enable display of hidden files
echo "👁️ Enabling display of hidden files..."

defaults write com.apple.finder AppleShowAllFiles -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Hidden files will now be visible in Finder"
    echo "⚠️  Warning: Hidden files contain system data - modify with caution"
else
    echo "❌ Failed to update hidden file display setting"
    exit 1
fi

Interface Enhancement Settings

Enable Status Bar

#!/bin/bash

# Enable Finder status bar
echo "📊 Enabling Finder status bar..."

defaults write com.apple.finder ShowStatusBar -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Status bar enabled - shows item count and available space"
else
    echo "❌ Failed to enable status bar"
    exit 1
fi

Show Full Path in Title Bar

#!/bin/bash

# Enable full path display in title bar
echo "🛤️ Enabling full path display in title bar..."

defaults write com.apple.finder _FXShowPosixPathInTitle -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Full file paths will now appear in Finder title bar"
else
    echo "❌ Failed to enable path display in title bar"
    exit 1
fi

Keep Folders on Top When Sorting

#!/bin/bash

# Enable folders-first sorting
echo "📁 Enabling folders-first sorting..."

defaults write com.apple.finder _FXSortFoldersFirst -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Folders will now appear before files when sorting by name"
else
    echo "❌ Failed to update folder sorting preference"
    exit 1
fi

Security and Warning Settings

Enable Extension Change Warning

#!/bin/bash

# Enable warning before changing file extensions
echo "⚠️ Enabling file extension change warning..."

defaults write com.apple.finder FXEnableExtensionChangeWarning -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Warning dialog will appear before changing file extensions"
else
    echo "❌ Failed to enable extension change warning"
    exit 1
fi

Enable iCloud Drive Removal Warning

#!/bin/bash

# Enable warning before removing items from iCloud Drive
echo "☁️ Enabling iCloud Drive removal warning..."

defaults write com.apple.finder FXEnableRemoveFromICloudDriveWarning -bool true
killall Finder

if [ $? -eq 0 ]; then
    echo "✅ Warning dialog will appear before removing items from iCloud Drive"
else
    echo "❌ Failed to enable iCloud Drive removal warning"
    exit 1
fi

Expand Information Window Panes

#!/bin/bash

# Configure information window panes to be expanded by default
echo "🔍 Configuring information window panes..."

defaults write com.apple.finder FXInfoPanesExpanded -dict \
    General -bool true \
    OpenWith -bool true \
    Privileges -bool true

killall Finder

if [ $? -eq 0 ]; then
    echo "✅ General, Open With, and Privileges panes will be expanded by default"
else
    echo "❌ Failed to configure information window panes"
    exit 1
fi

Enterprise Finder Configuration Script

#!/bin/bash

# Roundfleet Finder Customization Tool
# Standardize Finder preferences across fleet devices

# Configuration
LOG_FILE="/var/log/roundfleet_finder.log"
BACKUP_DIR="/var/backups/roundfleet/finder"
CONFIG_FILE="/etc/roundfleet/finder_config.plist"

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

# Create backup directory
setup_directories() {
    if [[ ! -d "$BACKUP_DIR" ]]; then
        mkdir -p "$BACKUP_DIR"
        log_action "Created backup directory: $BACKUP_DIR"
    fi
    
    if [[ ! -d "$(dirname "$CONFIG_FILE")" ]]; then
        mkdir -p "$(dirname "$CONFIG_FILE")"
        log_action "Created configuration directory"
    fi
}

# Backup current Finder preferences
backup_current_settings() {
    local backup_file="$BACKUP_DIR/finder_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    echo "📦 Creating backup of current Finder settings..."
    
    # Export current Finder preferences
    defaults export com.apple.finder "$backup_file" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        echo "✅ Backup created: $backup_file"
        log_action "Backup created: $backup_file"
    else
        echo "⚠️  Warning: Could not create backup"
        log_action "Warning: Backup creation failed"
    fi
}

# Apply enterprise Finder configuration
apply_finder_configuration() {
    echo "🔧 Applying Roundfleet Finder configuration..."
    log_action "Starting Finder configuration deployment"
    
    # Desktop display settings
    echo "Configuring desktop display options..."
    defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true
    defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true
    defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true
    
    # File visibility settings
    echo "Configuring file visibility options..."
    defaults write NSGlobalDomain AppleShowAllExtensions -bool true
    defaults write com.apple.finder _FXSortFoldersFirst -bool true
    
    # Interface enhancements
    echo "Configuring interface elements..."
    defaults write com.apple.finder ShowStatusBar -bool true
    defaults write com.apple.finder _FXShowPosixPathInTitle -bool true
    
    # Security warnings
    echo "Configuring security warnings..."
    defaults write com.apple.finder FXEnableExtensionChangeWarning -bool true
    defaults write com.apple.finder FXEnableRemoveFromICloudDriveWarning -bool true
    
    # Information window configuration
    echo "Configuring information window panes..."
    defaults write com.apple.finder FXInfoPanesExpanded -dict \
        General -bool true \
        OpenWith -bool true \
        Privileges -bool true
    
    # Restart Finder to apply changes
    echo "Restarting Finder to apply changes..."
    killall Finder
    
    if [ $? -eq 0 ]; then
        echo "✅ Finder configuration applied successfully"
        log_action "Finder configuration deployment completed successfully"
    else
        echo "❌ Failed to restart Finder"
        log_action "Error: Failed to restart Finder"
        return 1
    fi
}

# Verify configuration deployment
verify_configuration() {
    echo "🔍 Verifying Finder configuration..."
    
    local verification_passed=true
    
    # Check desktop display settings
    if [[ "$(defaults read com.apple.finder ShowHardDrivesOnDesktop 2>/dev/null)" == "1" ]]; then
        echo "✅ Hard drives on desktop: Enabled"
    else
        echo "❌ Hard drives on desktop: Failed"
        verification_passed=false
    fi
    
    if [[ "$(defaults read com.apple.finder ShowExternalHardDrivesOnDesktop 2>/dev/null)" == "1" ]]; then
        echo "✅ External drives on desktop: Enabled"
    else
        echo "❌ External drives on desktop: Failed"
        verification_passed=false
    fi
    
    # Check file visibility
    if [[ "$(defaults read NSGlobalDomain AppleShowAllExtensions 2>/dev/null)" == "1" ]]; then
        echo "✅ Show all extensions: Enabled"
    else
        echo "❌ Show all extensions: Failed"
        verification_passed=false
    fi
    
    # Check interface elements
    if [[ "$(defaults read com.apple.finder ShowStatusBar 2>/dev/null)" == "1" ]]; then
        echo "✅ Status bar: Enabled"
    else
        echo "❌ Status bar: Failed"
        verification_passed=false
    fi
    
    if $verification_passed; then
        echo "✅ All Finder configurations verified successfully"
        log_action "Configuration verification passed"
        return 0
    else
        echo "❌ Some configurations failed verification"
        log_action "Configuration verification failed"
        return 1
    fi
}

# Generate configuration report
generate_report() {
    local report_file="/tmp/finder_config_report_$(date +%Y%m%d_%H%M%S).txt"
    
    {
        echo "Roundfleet Finder Configuration Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "User: $(whoami)"
        echo "======================================"
        echo ""
        
        echo "Desktop Display Settings:"
        echo "Hard drives on desktop: $(defaults read com.apple.finder ShowHardDrivesOnDesktop 2>/dev/null || echo 'Not set')"
        echo "External drives on desktop: $(defaults read com.apple.finder ShowExternalHardDrivesOnDesktop 2>/dev/null || echo 'Not set')"
        echo "Removable media on desktop: $(defaults read com.apple.finder ShowRemovableMediaOnDesktop 2>/dev/null || echo 'Not set')"
        echo ""
        
        echo "File Visibility Settings:"
        echo "Show all extensions: $(defaults read NSGlobalDomain AppleShowAllExtensions 2>/dev/null || echo 'Not set')"
        echo "Show hidden files: $(defaults read com.apple.finder AppleShowAllFiles 2>/dev/null || echo 'Not set')"
        echo "Folders first: $(defaults read com.apple.finder _FXSortFoldersFirst 2>/dev/null || echo 'Not set')"
        echo ""
        
        echo "Interface Settings:"
        echo "Status bar: $(defaults read com.apple.finder ShowStatusBar 2>/dev/null || echo 'Not set')"
        echo "Path in title: $(defaults read com.apple.finder _FXShowPosixPathInTitle 2>/dev/null || echo 'Not set')"
        echo ""
        
        echo "Security Settings:"
        echo "Extension change warning: $(defaults read com.apple.finder FXEnableExtensionChangeWarning 2>/dev/null || echo 'Not set')"
        echo "iCloud removal warning: $(defaults read com.apple.finder FXEnableRemoveFromICloudDriveWarning 2>/dev/null || echo 'Not set')"
        
    } > "$report_file"
    
    echo "📊 Configuration report saved to: $report_file"
    log_action "Configuration report generated: $report_file"
}

# Restore from backup
restore_from_backup() {
    local backup_file="$1"
    
    if [[ ! -f "$backup_file" ]]; then
        echo "❌ Backup file not found: $backup_file"
        return 1
    fi
    
    echo "🔄 Restoring Finder settings from backup..."
    
    # Import backup
    defaults import com.apple.finder "$backup_file"
    
    if [ $? -eq 0 ]; then
        echo "✅ Settings restored from backup"
        killall Finder
        log_action "Settings restored from backup: $backup_file"
    else
        echo "❌ Failed to restore from backup"
        log_action "Error: Failed to restore from backup: $backup_file"
        return 1
    fi
}

# Reset to defaults
reset_to_defaults() {
    echo "🔄 Resetting Finder to default settings..."
    
    # Remove custom settings
    defaults delete com.apple.finder ShowHardDrivesOnDesktop 2>/dev/null
    defaults delete com.apple.finder ShowExternalHardDrivesOnDesktop 2>/dev/null
    defaults delete com.apple.finder ShowRemovableMediaOnDesktop 2>/dev/null
    defaults delete NSGlobalDomain AppleShowAllExtensions 2>/dev/null
    defaults delete com.apple.finder AppleShowAllFiles 2>/dev/null
    defaults delete com.apple.finder ShowStatusBar 2>/dev/null
    defaults delete com.apple.finder _FXShowPosixPathInTitle 2>/dev/null
    defaults delete com.apple.finder _FXSortFoldersFirst 2>/dev/null
    defaults delete com.apple.finder FXEnableExtensionChangeWarning 2>/dev/null
    defaults delete com.apple.finder FXEnableRemoveFromICloudDriveWarning 2>/dev/null
    defaults delete com.apple.finder FXInfoPanesExpanded 2>/dev/null
    
    killall Finder
    
    echo "✅ Finder reset to default settings"
    log_action "Finder reset to default settings"
}

# Main execution function
main() {
    local action="${1:-deploy}"
    
    log_action "=== Roundfleet Finder Customization Started ==="
    
    setup_directories
    
    case "$action" in
        "deploy")
            backup_current_settings
            apply_finder_configuration
            verify_configuration
            generate_report
            ;;
        "verify")
            verify_configuration
            ;;
        "report")
            generate_report
            ;;
        "restore")
            if [[ -n "$2" ]]; then
                restore_from_backup "$2"
            else
                echo "❌ Please specify backup file path"
                echo "Usage: $0 restore /path/to/backup.plist"
                exit 1
            fi
            ;;
        "reset")
            backup_current_settings
            reset_to_defaults
            ;;
        *)
            echo "Usage: $0 [deploy|verify|report|restore|reset]"
            echo ""
            echo "Commands:"
            echo "  deploy  - Apply Roundfleet Finder configuration (default)"
            echo "  verify  - Verify current configuration"
            echo "  report  - Generate configuration report"
            echo "  restore - Restore from backup file"
            echo "  reset   - Reset to default settings"
            exit 1
            ;;
    esac
    
    log_action "=== Roundfleet Finder Customization Completed ==="
}

# Execute main function
main "$@"

Configuration Reference

SettingCommandDescription
Hard drives on desktopShowHardDrivesOnDesktopDisplay internal drives on desktop
External drives on desktopShowExternalHardDrivesOnDesktopDisplay external drives on desktop
Removable media on desktopShowRemovableMediaOnDesktopDisplay CDs, DVDs, iPods on desktop
Show all extensionsAppleShowAllExtensionsDisplay file extensions for all files
Show hidden filesAppleShowAllFilesDisplay normally hidden system files
Status barShowStatusBarShow item count and disk space
Path in title_FXShowPosixPathInTitleDisplay full path in window title
Folders first_FXSortFoldersFirstSort folders before files
Extension warningFXEnableExtensionChangeWarningWarn before changing extensions
iCloud warningFXEnableRemoveFromICloudDriveWarningWarn before iCloud removal

Quick Reference Commands

Enable All Desktop Items

# Show all desktop items
defaults write com.apple.finder ShowHardDrivesOnDesktop -bool true
defaults write com.apple.finder ShowExternalHardDrivesOnDesktop -bool true
defaults write com.apple.finder ShowRemovableMediaOnDesktop -bool true
killall Finder

Enable Full Visibility

# Maximum file visibility
defaults write NSGlobalDomain AppleShowAllExtensions -bool true
defaults write com.apple.finder AppleShowAllFiles -bool true
defaults write com.apple.finder ShowStatusBar -bool true
killall Finder

Enable All Security Warnings

# Enable all security warnings
defaults write com.apple.finder FXEnableExtensionChangeWarning -bool true
defaults write com.apple.finder FXEnableRemoveFromICloudDriveWarning -bool true
killall Finder

Troubleshooting

Finder Not Restarting

# Force restart Finder
sudo pkill -f Finder
sleep 2
open /System/Library/CoreServices/Finder.app

Settings Not Applying

# Clear Finder cache and restart
sudo rm -rf ~/Library/Caches/com.apple.finder
killall Finder

Verify Settings Applied

# Check specific setting
defaults read com.apple.finder ShowStatusBar

# List all Finder settings
defaults read com.apple.finder

Security Considerations

  • Hidden files contain system data - modify with caution
  • File extensions help identify file types - consider security implications
  • Desktop items may clutter interface in shared environments
  • Test changes on individual devices before fleet deployment
  • Create backups before applying configuration changes

Important Notes

  • Changes require Finder restart to take effect
  • Some settings apply system-wide (NSGlobalDomain)
  • User-specific settings don't affect other accounts
  • Administrative privileges may be required for system-wide deployment
  • Backup current settings before making changes for easy restoration

Find My Mac Security Management and Compliance

Ensure enterprise security compliance by monitoring and managing Find My Mac status across your Roundfleet devices. This tutorial covers security auditing, Apple ID verification, automated compliance reporting, and enterprise security policy enforcement.

Understanding Find My Mac Security

Find My Mac is Apple's built-in device location and security service that provides:

  • Device Location Tracking - Real-time location services for lost or stolen devices
  • Remote Lock and Wipe - Secure device data remotely
  • Activation Lock - Prevents unauthorized device reactivation
  • Security Integration - Works with Apple ID and iCloud services

Basic Find My Mac Status Check

Simple Status Verification

#!/bin/bash

# Basic Find My Mac status check
fmmToken=$(/usr/sbin/nvram -x -p | /usr/bin/grep fmm-mobileme-token-FMM)

if [ -z "$fmmToken" ]; then
    echo "Find My Mac is disabled"
else
    echo "Find My Mac is enabled"
fi

Enhanced Status Check with Details

#!/bin/bash

# Enhanced Find My Mac verification
check_find_my_mac_basic() {
    echo "=== Find My Mac Status Check ==="
    
    # Check for Find My Mac token
    local fmm_token
    fmm_token=$(/usr/sbin/nvram -x -p | /usr/bin/grep fmm-mobileme-token-FMM 2>/dev/null)
    
    if [ -z "$fmm_token" ]; then
        echo "❌ Find My Mac: DISABLED"
        return 1
    else
        echo "✅ Find My Mac: ENABLED"
        
        # Extract additional details if available
        echo "Token found in NVRAM"
        return 0
    fi
}

# Execute the check
check_find_my_mac_basic

Enterprise Security Management Script

#!/bin/bash

# Roundfleet Find My Mac Security Management
# Comprehensive security auditing and compliance monitoring

# Configuration
LOG_FILE="/var/log/roundfleet_security.log"
REPORT_DIR="/var/reports/security"
COMPLIANCE_DIR="/var/compliance"
TEMP_DIR="/tmp/roundfleet_security"

# Security policies configuration
REQUIRE_FIND_MY_MAC=true
REQUIRE_APPLE_ID=true
REQUIRE_ACTIVATION_LOCK=true
MAX_OFFLINE_DAYS=30

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

# Create necessary directories
setup_directories() {
    for dir in "$REPORT_DIR" "$COMPLIANCE_DIR" "$TEMP_DIR"; do
        if [[ ! -d "$dir" ]]; then
            mkdir -p "$dir"
            log_action "Created directory: $dir"
        fi
    done
}

# Check Find My Mac status with detailed analysis
check_find_my_mac_status() {
    log_action "Checking Find My Mac status"
    
    local status_report="$TEMP_DIR/fmm_status.json"
    
    # Initialize status object
    cat > "$status_report" << EOF
{
    "timestamp": "$(date -Iseconds)",
    "hostname": "$(hostname)",
    "find_my_mac": {
        "enabled": false,
        "token_present": false,
        "activation_lock": false,
        "apple_id_signed_in": false
    },
    "compliance": {
        "status": "non_compliant",
        "issues": []
    }
}
EOF

    # Check for Find My Mac token in NVRAM
    local fmm_token
    fmm_token=$(/usr/sbin/nvram -x -p | /usr/bin/grep fmm-mobileme-token-FMM 2>/dev/null)
    
    if [[ -n "$fmm_token" ]]; then
        log_action "✅ Find My Mac token found in NVRAM"
        
        # Update JSON status
        /usr/bin/python3 -c "
import json
with open('$status_report', 'r') as f:
    data = json.load(f)
data['find_my_mac']['enabled'] = True
data['find_my_mac']['token_present'] = True
with open('$status_report', 'w') as f:
    json.dump(data, f, indent=2)
"
        echo "enabled"
    else
        log_action "❌ Find My Mac not enabled - no token found"
        
        # Add compliance issue
        /usr/bin/python3 -c "
import json
with open('$status_report', 'r') as f:
    data = json.load(f)
data['compliance']['issues'].append('Find My Mac not enabled')
with open('$status_report', 'w') as f:
    json.dump(data, f, indent=2)
"
        echo "disabled"
    fi
}

# Check Apple ID sign-in status
check_apple_id_status() {
    log_action "Checking Apple ID sign-in status"
    
    # Check if user is signed into iCloud
    local icloud_account
    icloud_account=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep -c AccountID || echo "0")
    
    if [[ "$icloud_account" -gt 0 ]]; then
        log_action "✅ Apple ID signed in to iCloud"
        
        # Get Apple ID details (masked for privacy)
        local apple_id_info
        apple_id_info=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep AccountID | head -1 | sed 's/.*= "\(.*\)";/\1/' | sed 's/\(.*@\)\(.*\)/\1***/g')
        log_action "Apple ID: $apple_id_info"
        
        return 0
    else
        log_action "❌ No Apple ID signed in"
        return 1
    fi
}

# Check system integrity and security settings
check_system_security() {
    log_action "Performing system security audit"
    
    local security_report="$TEMP_DIR/security_audit.json"
    
    cat > "$security_report" << EOF
{
    "timestamp": "$(date -Iseconds)",
    "hostname": "$(hostname)",
    "security_audit": {
        "sip_status": "unknown",
        "gatekeeper_status": "unknown",
        "filevault_status": "unknown",
        "firewall_status": "unknown",
        "secure_boot": "unknown"
    }
}
EOF

    # Check System Integrity Protection (SIP)
    local sip_status
    sip_status=$(csrutil status 2>/dev/null | grep -i enabled && echo "enabled" || echo "disabled")
    log_action "SIP Status: $sip_status"
    
    # Check Gatekeeper
    local gatekeeper_status
    gatekeeper_status=$(spctl --status 2>/dev/null | grep -i enabled && echo "enabled" || echo "disabled")
    log_action "Gatekeeper Status: $gatekeeper_status"
    
    # Check FileVault
    local filevault_status
    filevault_status=$(fdesetup status 2>/dev/null | grep -i "on" && echo "enabled" || echo "disabled")
    log_action "FileVault Status: $filevault_status"
    
    # Check Firewall
    local firewall_status
    firewall_status=$(/usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate 2>/dev/null | grep -i enabled && echo "enabled" || echo "disabled")
    log_action "Firewall Status: $firewall_status"
    
    # Update security report
    /usr/bin/python3 -c "
import json
with open('$security_report', 'r') as f:
    data = json.load(f)
data['security_audit']['sip_status'] = '$sip_status'
data['security_audit']['gatekeeper_status'] = '$gatekeeper_status'
data['security_audit']['filevault_status'] = '$filevault_status'
data['security_audit']['firewall_status'] = '$firewall_status'
with open('$security_report', 'w') as f:
    json.dump(data, f, indent=2)
"

    echo "$security_report"
}

# Check activation lock status
check_activation_lock() {
    log_action "Checking Activation Lock status"
    
    # Check if device has activation lock enabled
    # This requires checking with Apple's servers or MDM enrollment
    local activation_lock_status="unknown"
    
    # For enterprise devices, check MDM enrollment
    if profiles -P 2>/dev/null | grep -q "com.apple.mdm"; then
        log_action "✅ Device is MDM enrolled"
        activation_lock_status="mdm_managed"
    else
        log_action "⚠️  Device not MDM enrolled"
        activation_lock_status="not_managed"
    fi
    
    # Check for DEP/ABM enrollment
    if profiles -e 2>/dev/null | grep -q "DEP"; then
        log_action "✅ Device is DEP/ABM enrolled"
        activation_lock_status="dep_enrolled"
    fi
    
    echo "$activation_lock_status"
}

# Generate comprehensive security report
generate_security_report() {
    local report_timestamp
    report_timestamp=$(date '+%Y%m%d_%H%M%S')
    local report_file="$REPORT_DIR/security_report_$report_timestamp.json"
    
    log_action "Generating comprehensive security report: $report_file"
    
    # Get system information
    local os_version
    local serial_number
    local hardware_uuid
    os_version=$(sw_vers -productVersion)
    serial_number=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
    hardware_uuid=$(system_profiler SPHardwareDataType | grep "Hardware UUID" | awk '{print $3}')
    
    # Compile comprehensive report
    cat > "$report_file" << EOF
{
    "report_metadata": {
        "timestamp": "$(date -Iseconds)",
        "report_version": "1.0",
        "generator": "Roundfleet Security Audit"
    },
    "device_info": {
        "hostname": "$(hostname)",
        "serial_number": "$serial_number",
        "hardware_uuid": "$hardware_uuid",
        "os_version": "$os_version",
        "model": "$(system_profiler SPHardwareDataType | grep "Model Name" | awk -F': ' '{print $2}')"
    },
    "security_status": {
        "find_my_mac": {
            "enabled": $(check_find_my_mac_status >/dev/null && echo "true" || echo "false"),
            "compliance": $([ "$REQUIRE_FIND_MY_MAC" = true ] && check_find_my_mac_status >/dev/null && echo "true" || echo "false")
        },
        "apple_id": {
            "signed_in": $(check_apple_id_status >/dev/null && echo "true" || echo "false"),
            "compliance": $([ "$REQUIRE_APPLE_ID" = true ] && check_apple_id_status >/dev/null && echo "true" || echo "false")
        },
        "activation_lock": {
            "status": "$(check_activation_lock)",
            "compliance": $([ "$REQUIRE_ACTIVATION_LOCK" = true ] && echo "true" || echo "false")
        }
    },
    "compliance_summary": {
        "overall_status": "$(calculate_compliance_status)",
        "required_actions": $(generate_required_actions),
        "risk_level": "$(calculate_risk_level)"
    }
}
EOF

    log_action "Security report generated: $report_file"
    echo "$report_file"
}

# Calculate overall compliance status
calculate_compliance_status() {
    local fmm_status
    local apple_id_status
    local issues=0
    
    fmm_status=$(check_find_my_mac_status)
    if [[ "$REQUIRE_FIND_MY_MAC" = true && "$fmm_status" != "enabled" ]]; then
        ((issues++))
    fi
    
    if ! check_apple_id_status >/dev/null 2>&1; then
        if [[ "$REQUIRE_APPLE_ID" = true ]]; then
            ((issues++))
        fi
    fi
    
    if [[ $issues -eq 0 ]]; then
        echo "compliant"
    elif [[ $issues -le 2 ]]; then
        echo "partially_compliant"
    else
        echo "non_compliant"
    fi
}

# Generate required actions for compliance
generate_required_actions() {
    local actions=()
    
    if [[ "$REQUIRE_FIND_MY_MAC" = true ]] && [[ "$(check_find_my_mac_status)" != "enabled" ]]; then
        actions+=("\"Enable Find My Mac in System Preferences\"")
    fi
    
    if [[ "$REQUIRE_APPLE_ID" = true ]] && ! check_apple_id_status >/dev/null 2>&1; then
        actions+=("\"Sign in with Apple ID in System Preferences\"")
    fi
    
    if [[ ${#actions[@]} -eq 0 ]]; then
        echo "[]"
    else
        printf "[%s]" "$(IFS=,; echo "${actions[*]}")"
    fi
}

# Calculate risk level based on security status
calculate_risk_level() {
    local risk_score=0
    
    # Find My Mac disabled adds risk
    if [[ "$(check_find_my_mac_status)" != "enabled" ]]; then
        ((risk_score += 3))
    fi
    
    # No Apple ID adds risk
    if ! check_apple_id_status >/dev/null 2>&1; then
        ((risk_score += 2))
    fi
    
    # System security issues add risk
    if [[ "$(csrutil status 2>/dev/null | grep -i disabled)" ]]; then
        ((risk_score += 2))
    fi
    
    if [[ $risk_score -le 1 ]]; then
        echo "low"
    elif [[ $risk_score -le 4 ]]; then
        echo "medium"
    else
        echo "high"
    fi
}

# Remediation actions for common issues
remediate_security_issues() {
    log_action "Starting automated remediation process"
    
    local remediation_report="$TEMP_DIR/remediation_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$remediation_report" << EOF
{
    "timestamp": "$(date -Iseconds)",
    "hostname": "$(hostname)",
    "remediation_actions": []
}
EOF

    # Check if Find My Mac can be enabled programmatically
    if [[ "$(check_find_my_mac_status)" != "enabled" ]]; then
        log_action "⚠️  Find My Mac is disabled - manual intervention required"
        log_action "   User must enable Find My Mac in System Preferences > Apple ID > Find My"
        
        # Add to remediation report
        /usr/bin/python3 -c "
import json
with open('$remediation_report', 'r') as f:
    data = json.load(f)
data['remediation_actions'].append({
    'issue': 'Find My Mac disabled',
    'action': 'manual_intervention_required',
    'instructions': 'Enable Find My Mac in System Preferences > Apple ID > Find My'
})
with open('$remediation_report', 'w') as f:
    json.dump(data, f, indent=2)
"
    fi
    
    # Generate user notification if needed
    if [[ "$(calculate_compliance_status)" != "compliant" ]]; then
        create_user_notification
    fi
    
    echo "$remediation_report"
}

# Create user notification for security compliance
create_user_notification() {
    log_action "Creating user notification for security compliance"
    
    local notification_title="Roundfleet Security Compliance"
    local notification_message="Your device requires security configuration updates. Please contact IT support."
    
    # Use AppleScript to show notification
    osascript -e "display notification \"$notification_message\" with title \"$notification_title\""
    
    # Create persistent reminder file
    cat > "/tmp/roundfleet_security_reminder.txt" << EOF
Roundfleet Security Compliance Required

Your device needs the following security features enabled:
- Find My Mac
- Apple ID sign-in
- Activation Lock

Please contact IT support for assistance.
Generated: $(date)
EOF
}

# Monitor Find My Mac status over time
monitor_security_status() {
    log_action "Starting continuous security monitoring"
    
    local monitoring_interval=3600  # 1 hour
    local monitoring_log="$LOG_FILE.monitoring"
    
    while true; do
        {
            echo "=== Security Status Check - $(date) ==="
            echo "Find My Mac: $(check_find_my_mac_status)"
            echo "Apple ID: $(check_apple_id_status >/dev/null && echo "signed_in" || echo "not_signed_in")"
            echo "Compliance: $(calculate_compliance_status)"
            echo "Risk Level: $(calculate_risk_level)"
            echo "----------------------------------------"
        } >> "$monitoring_log"
        
        sleep "$monitoring_interval"
    done
}

# Fleet-wide security assessment
fleet_security_assessment() {
    log_action "Performing fleet-wide security assessment"
    
    local fleet_report="$REPORT_DIR/fleet_security_$(date '+%Y%m%d_%H%M%S').json"
    
    # This would typically integrate with MDM or configuration management
    # For demonstration, we'll show the current device assessment
    
    cat > "$fleet_report" << EOF
{
    "assessment_timestamp": "$(date -Iseconds)",
    "fleet_summary": {
        "total_devices": 1,
        "compliant_devices": $([ "$(calculate_compliance_status)" = "compliant" ] && echo "1" || echo "0"),
        "non_compliant_devices": $([ "$(calculate_compliance_status)" != "compliant" ] && echo "1" || echo "0")
    },
    "devices": [
        $(generate_security_report | tail -n +2 | head -n -1)
    ],
    "recommendations": [
        "Implement automated Find My Mac enablement via MDM",
        "Enforce Apple ID sign-in through device enrollment",
        "Regular security compliance auditing",
        "User education on security features"
    ]
}
EOF

    log_action "Fleet security assessment completed: $fleet_report"
    echo "$fleet_report"
}

# Main execution function
main() {
    local action="${1:-check}"
    
    log_action "=== Roundfleet Security Management Started ==="
    log_action "Action: $action"
    log_action "Hostname: $(hostname)"
    log_action "User: $(whoami)"
    
    # Setup
    setup_directories
    
    case "$action" in
        "check")
            echo "=== Find My Mac Security Check ==="
            echo "Find My Mac Status: $(check_find_my_mac_status)"
            echo "Apple ID Status: $(check_apple_id_status >/dev/null && echo "signed_in" || echo "not_signed_in")"
            echo "Activation Lock: $(check_activation_lock)"
            echo "Compliance Status: $(calculate_compliance_status)"
            echo "Risk Level: $(calculate_risk_level)"
            ;;
        "audit")
            echo "Performing comprehensive security audit..."
            security_report=$(generate_security_report)
            echo "Security audit completed: $security_report"
            ;;
        "remediate")
            echo "Starting remediation process..."
            remediation_report=$(remediate_security_issues)
            echo "Remediation completed: $remediation_report"
            ;;
        "monitor")
            echo "Starting continuous monitoring..."
            monitor_security_status
            ;;
        "fleet")
            echo "Performing fleet-wide assessment..."
            fleet_report=$(fleet_security_assessment)
            echo "Fleet assessment completed: $fleet_report"
            ;;
        *)
            echo "Usage: $0 {check|audit|remediate|monitor|fleet}"
            echo "  check     - Quick security status check"
            echo "  audit     - Comprehensive security audit"
            echo "  remediate - Automated remediation actions"
            echo "  monitor   - Continuous security monitoring"
            echo "  fleet     - Fleet-wide security assessment"
            exit 1
            ;;
    esac
    
    # Cleanup
    rm -rf "$TEMP_DIR"
    
    log_action "=== Security management completed ==="
}

# Execute main function
main "$@"

Apple ID and iCloud Integration

Check Apple ID Sign-in Status

#!/bin/bash

# Comprehensive Apple ID verification
check_apple_id_comprehensive() {
    echo "=== Apple ID Status Check ==="
    
    # Check iCloud accounts
    local icloud_accounts
    icloud_accounts=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep -c AccountID || echo "0")
    
    if [[ "$icloud_accounts" -gt 0 ]]; then
        echo "✅ Apple ID signed in ($icloud_accounts account(s))"
        
        # Get account details (privacy-safe)
        defaults read MobileMeAccounts Accounts 2>/dev/null | grep AccountID | while read -r line; do
            local account_id
            account_id=$(echo "$line" | sed 's/.*= "\(.*\)";/\1/' | sed 's/\(.*@\)\(.*\)/\1***/g')
            echo "   Account: $account_id"
        done
        
        # Check iCloud services
        echo "iCloud Services:"
        defaults read MobileMeAccounts Accounts 2>/dev/null | grep -E "(BookmarksSyncEnabled|ContactsSyncEnabled|MailSyncEnabled)" | while read -r service; do
            echo "   $service"
        done
        
        return 0
    else
        echo "❌ No Apple ID signed in"
        return 1
    fi
}

Verify iCloud Services Status

#!/bin/bash

# Check specific iCloud services
check_icloud_services() {
    echo "=== iCloud Services Status ==="
    
    # Check Find My Mac specifically
    local fmf_token
    fmf_token=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep -i findmyfriends || echo "")
    
    if [[ -n "$fmf_token" ]]; then
        echo "✅ Find My Friends/Family service active"
    else
        echo "⚠️  Find My Friends/Family service not configured"
    fi
    
    # Check other critical services
    local services=(
        "BookmarksSyncEnabled:Safari Bookmarks"
        "ContactsSyncEnabled:Contacts"
        "CalendarSyncEnabled:Calendar"
        "KeychainSyncEnabled:Keychain"
    )
    
    for service in "${services[@]}"; do
        local key="${service%%:*}"
        local name="${service##*:}"
        local status
        status=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep "$key" | head -1 | grep -o "[01]" || echo "0")
        
        if [[ "$status" = "1" ]]; then
            echo "✅ $name sync enabled"
        else
            echo "❌ $name sync disabled"
        fi
    done
}

Enterprise Security Policies

Define Security Requirements

#!/bin/bash

# Enterprise security policy configuration
apply_security_policies() {
    echo "=== Applying Enterprise Security Policies ==="
    
    local policy_file="/etc/roundfleet/security_policies.json"
    
    # Create security policy configuration
    mkdir -p "$(dirname "$policy_file")"
    cat > "$policy_file" << 'EOF'
{
    "security_policies": {
        "find_my_mac": {
            "required": true,
            "enforcement": "advisory",
            "grace_period_days": 7
        },
        "apple_id": {
            "required": true,
            "corporate_domain_only": false,
            "enforcement": "mandatory"
        },
        "activation_lock": {
            "required": true,
            "mdm_managed": true
        },
        "system_security": {
            "sip_required": true,
            "gatekeeper_required": true,
            "filevault_required": true,
            "firewall_required": true
        }
    },
    "compliance_reporting": {
        "frequency": "daily",
        "recipients": ["[email protected]"],
        "escalation_threshold": "medium"
    }
}
EOF

    echo "Security policies configured: $policy_file"
}

Compliance Monitoring

#!/bin/bash

# Automated compliance monitoring
setup_compliance_monitoring() {
    local monitoring_script="/usr/local/bin/roundfleet_compliance_monitor.sh"
    local launchd_plist="/Library/LaunchDaemons/com.roundfleet.security.compliance.plist"
    
    # Create monitoring script
    cat > "$monitoring_script" << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/roundfleet_compliance.log"
exec > >(tee -a "$LOG_FILE") 2>&1

echo "$(date): Starting security compliance check"

# Run security audit
/usr/local/bin/roundfleet_security_manager.sh audit

# Check for non-compliance
COMPLIANCE_STATUS=$(calculate_compliance_status)
if [[ "$COMPLIANCE_STATUS" != "compliant" ]]; then
    echo "$(date): Non-compliance detected - $COMPLIANCE_STATUS"
    
    # Send alert (implement according to your notification system)
    echo "Device $(hostname) is non-compliant" | mail -s "Security Compliance Alert" [email protected]
fi

echo "$(date): Compliance check completed"
EOF

    chmod +x "$monitoring_script"
    
    # Create LaunchDaemon for scheduled compliance checks
    cat > "$launchd_plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.roundfleet.security.compliance</string>
    <key>ProgramArguments</key>
    <array>
        <string>$monitoring_script</string>
    </array>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>9</integer>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
        <dict>
            <key>Hour</key>
            <integer>17</integer>
            <key>Minute</key>
            <integer>0</integer>
        </dict>
    </array>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF

    # Load the LaunchDaemon
    sudo launchctl load "$launchd_plist"
    
    echo "Compliance monitoring configured"
    echo "Script: $monitoring_script"
    echo "Schedule: Daily at 9:00 AM and 5:00 PM"
}

Security Status Indicators

Understanding NVRAM Tokens

The Find My Mac status is stored in NVRAM (Non-Volatile Random Access Memory) tokens:

TokenDescriptionIndicates
fmm-mobileme-token-FMMPrimary Find My Mac tokenService is active and configured
fmm-computer-nameDevice name for Find MyDevice identification in Find My network
fmm-mobileme-token-FMFFind My Friends tokenLocation sharing services

Interpreting Security States

StateFind My MacApple IDComplianceAction Required
Fully Compliant✅ Enabled✅ Signed In✅ CompliantNone
Partially Compliant✅ Enabled❌ Not Signed In⚠️ PartialSign in to Apple ID
Non-Compliant❌ Disabled❌ Not Signed In❌ Non-CompliantEnable Find My Mac and sign in
Unknown State❓ Cannot Detect❓ Cannot Detect❓ UnknownManual verification required

Troubleshooting Common Issues

Find My Mac Not Enabling

#!/bin/bash

# Troubleshoot Find My Mac issues
troubleshoot_find_my_mac() {
    echo "=== Find My Mac Troubleshooting ==="
    
    # Check prerequisites
    echo "Checking prerequisites..."
    
    # 1. Check internet connectivity
    if ping -c 1 apple.com >/dev/null 2>&1; then
        echo "✅ Internet connectivity: OK"
    else
        echo "❌ Internet connectivity: FAILED"
        echo "   - Check network connection"
        echo "   - Verify DNS settings"
    fi
    
    # 2. Check Apple ID sign-in
    if check_apple_id_status >/dev/null 2>&1; then
        echo "✅ Apple ID sign-in: OK"
    else
        echo "❌ Apple ID sign-in: REQUIRED"
        echo "   - Sign in to Apple ID in System Preferences"
        echo "   - Enable iCloud services"
    fi
    
    # 3. Check iCloud services
    local icloud_enabled
    icloud_enabled=$(defaults read MobileMeAccounts Accounts 2>/dev/null | grep -c "Enabled.*1" || echo "0")
    
    if [[ "$icloud_enabled" -gt 0 ]]; then
        echo "✅ iCloud services: ENABLED"
    else
        echo "❌ iCloud services: DISABLED"
        echo "   - Enable iCloud in System Preferences"
        echo "   - Ensure Find My Mac is checked"
    fi
    
    # 4. Check system requirements
    local os_version
    os_version=$(sw_vers -productVersion)
    
    if [[ "$(echo "$os_version" | cut -d. -f1)" -ge 10 ]] && [[ "$(echo "$os_version" | cut -d. -f2)" -ge 11 ]]; then
        echo "✅ macOS version: SUPPORTED ($os_version)"
    else
        echo "❌ macOS version: UNSUPPORTED ($os_version)"
        echo "   - Find My Mac requires macOS 10.11 or later"
    fi
}

Manual Remediation Steps

#!/bin/bash

# Generate manual remediation guide
generate_remediation_guide() {
    local guide_file="/tmp/roundfleet_remediation_guide.txt"
    
    cat > "$guide_file" << EOF
Roundfleet Security Remediation Guide
==================================

Device: $(hostname)
Date: $(date)

Required Actions:
EOF

    if [[ "$(check_find_my_mac_status)" != "enabled" ]]; then
        cat >> "$guide_file" << EOF

1. Enable Find My Mac:
   - Open System Preferences
   - Click on Apple ID (or iCloud on older systems)
   - Sign in with your Apple ID if not already signed in
   - Click on "Find My" in the sidebar
   - Check "Find My Mac"
   - Check "Enable offline finding" (if available)
   - Click "Allow" when prompted for location access

EOF
    fi
    
    if ! check_apple_id_status >/dev/null 2>&1; then
        cat >> "$guide_file" << EOF

2. Sign in to Apple ID:
   - Open System Preferences
   - Click on Apple ID at the top
   - Enter your Apple ID and password
   - Complete two-factor authentication if prompted
   - Enable iCloud services as needed

EOF
    fi
    
    cat >> "$guide_file" << EOF

For assistance, contact IT Support:
- Email: [email protected]
- Phone: +1-555-0123
- Ticket System: https://support.company.com

EOF

    echo "Remediation guide created: $guide_file"
    open "$guide_file"
}

Best Practices

🔐 Security Guidelines

  • Enable Find My Mac on all enterprise devices
  • Require Apple ID sign-in for device accountability
  • Monitor compliance status regularly
  • Implement automated alerting for non-compliance

📋 Management Recommendations

  • Use MDM enrollment for enterprise activation lock
  • Regular security audits across device fleet
  • User education on security feature importance
  • Automated compliance monitoring and reporting

🔍 Monitoring Strategy

  • Daily compliance checks during business hours
  • Immediate alerts for security violations
  • Trend analysis of compliance metrics
  • Regular policy review and updates

Important Notes

  • Find My Mac requires macOS 10.11 or later for full functionality
  • Apple ID sign-in is mandatory for Find My Mac operation
  • Network connectivity required for initial setup and ongoing operation
  • Privacy considerations should be documented for enterprise use
  • Test remediation procedures before enterprise deployment

FileVault Encryption Management on macOS

Manage FileVault disk encryption across your Roundfleet deployment with comprehensive monitoring, compliance reporting, and automated encryption management. This tutorial provides enterprise-grade solutions for maintaining data security through disk encryption.

Understanding FileVault Encryption

FileVault is Apple's full-disk encryption technology that protects data at rest on macOS devices:

  • Full Disk Encryption - Encrypts entire startup disk
  • XTS-AES-128 encryption algorithm with 256-bit key
  • Hardware acceleration on supported Mac devices
  • Recovery key management for enterprise deployment
  • Compliance requirements for data protection standards

Basic Encryption Status Monitoring

Check FileVault Status

#!/bin/bash

# Check current FileVault encryption status
sudo fdesetup status

echo "FileVault status check completed"

Verify Encryption State

#!/bin/bash

# Get detailed encryption information
echo "=== FileVault Status ==="
status=$(sudo fdesetup status)
echo "$status"

# Parse status for automation
if echo "$status" | grep -q "FileVault is On"; then
    echo "✅ Encryption: ENABLED"
    exit 0
elif echo "$status" | grep -q "FileVault is Off"; then
    echo "❌ Encryption: DISABLED"
    exit 1
else
    echo "⚠️ Encryption: UNKNOWN STATE"
    exit 2
fi

Encryption Progress Monitoring

macOS 10.11 and 10.12 (Core Storage)

#!/bin/bash

# Monitor encryption/decryption progress for older macOS versions
echo "=== Core Storage Encryption Progress ==="
progress=$(diskutil cs list | grep "Conversion Progress")

if [[ -n "$progress" ]]; then
    echo "Encryption in progress:"
    echo "$progress"
else
    echo "No encryption/decryption operation in progress"
fi

macOS 10.13+ (APFS)

#!/bin/bash

# Monitor encryption progress for APFS (macOS 10.13+)
echo "=== APFS Encryption Progress ==="

# Check encryption progress
enc_progress=$(diskutil apfs list | grep "Encryption Progress")
if [[ -n "$enc_progress" ]]; then
    echo "Encryption in progress:"
    echo "$enc_progress"
fi

# Check decryption progress
dec_progress=$(diskutil apfs list | grep "Decryption Progress")
if [[ -n "$dec_progress" ]]; then
    echo "Decryption in progress:"
    echo "$dec_progress"
fi

if [[ -z "$enc_progress" && -z "$dec_progress" ]]; then
    echo "No encryption/decryption operation in progress"
fi

Universal Progress Monitor

#!/bin/bash

# Universal encryption progress monitor
check_encryption_progress() {
    local macos_version
    macos_version=$(sw_vers -productVersion | cut -d. -f1-2)
    
    echo "=== Encryption Progress Monitor ==="
    echo "macOS Version: $macos_version"
    
    case "$macos_version" in
        "10.11"|"10.12")
            echo "Using Core Storage monitoring..."
            diskutil cs list | grep "Conversion Progress" || echo "No progress detected"
            ;;
        *)
            echo "Using APFS monitoring..."
            local enc_progress dec_progress
            enc_progress=$(diskutil apfs list | grep "Encryption Progress")
            dec_progress=$(diskutil apfs list | grep "Decryption Progress")
            
            if [[ -n "$enc_progress" ]]; then
                echo "Encryption: $enc_progress"
            elif [[ -n "$dec_progress" ]]; then
                echo "Decryption: $dec_progress"
            else
                echo "No encryption/decryption operation in progress"
            fi
            ;;
    esac
}

check_encryption_progress

Advanced Enterprise Management

Comprehensive Encryption Audit

#!/bin/bash

# Roundfleet FileVault Enterprise Audit Tool
# Comprehensive encryption status and compliance checking

# Configuration
LOG_FILE="/var/log/roundfleet_encryption.log"
REPORT_DIR="/var/log/roundfleet_reports"
CONFIG_FILE="/etc/roundfleet/encryption_policy.conf"

# Create directories if they don't exist
mkdir -p "$(dirname "$LOG_FILE")" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")"

# Default configuration
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Encryption Policy Configuration
REQUIRE_FILEVAULT=true
ALERT_ON_DISABLED=true
MONITOR_PROGRESS=true
COMPLIANCE_REPORTING=true
AUTO_REMEDIATION=false
NOTIFICATION_EMAIL=""
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 system information
get_system_info() {
    echo "=== System Information ==="
    echo "Hostname: $(hostname)"
    echo "macOS Version: $(sw_vers -productVersion)"
    echo "Build: $(sw_vers -buildVersion)"
    echo "Hardware: $(system_profiler SPHardwareDataType | grep "Model Name" | awk -F: '{print $2}' | xargs)"
    echo "Serial: $(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
    echo "Audit Date: $(date)"
    echo ""
}

# Check FileVault status
check_filevault_status() {
    echo "=== FileVault Status Analysis ==="
    
    local status
    status=$(sudo fdesetup status 2>/dev/null)
    
    if echo "$status" | grep -q "FileVault is On"; then
        echo "✅ FileVault Status: ENABLED"
        log_action "FileVault encryption is properly enabled"
        
        # Get enabled users
        local enabled_users
        enabled_users=$(sudo fdesetup list 2>/dev/null)
        if [[ -n "$enabled_users" ]]; then
            echo "Enabled Users:"
            echo "$enabled_users"
        fi
        
        return 0
    elif echo "$status" | grep -q "FileVault is Off"; then
        echo "❌ FileVault Status: DISABLED"
        log_action "SECURITY ALERT: FileVault encryption is disabled"
        
        if [[ "$ALERT_ON_DISABLED" == "true" ]]; then
            echo "⚠️  COMPLIANCE VIOLATION: Encryption required by policy"
        fi
        
        return 1
    else
        echo "⚠️  FileVault Status: UNKNOWN"
        log_action "WARNING: Cannot determine FileVault status"
        return 2
    fi
}

# Check encryption progress
check_encryption_progress() {
    echo "=== Encryption Progress ==="
    
    local macos_version
    macos_version=$(sw_vers -productVersion | cut -d. -f1-2)
    
    case "$macos_version" in
        "10.11"|"10.12")
            local cs_progress
            cs_progress=$(diskutil cs list | grep "Conversion Progress")
            if [[ -n "$cs_progress" ]]; then
                echo "Core Storage Progress: $cs_progress"
                log_action "Encryption/Decryption in progress: $cs_progress"
            else
                echo "No Core Storage conversion in progress"
            fi
            ;;
        *)
            local enc_progress dec_progress
            enc_progress=$(diskutil apfs list | grep "Encryption Progress")
            dec_progress=$(diskutil apfs list | grep "Decryption Progress")
            
            if [[ -n "$enc_progress" ]]; then
                echo "APFS Encryption Progress: $enc_progress"
                log_action "APFS encryption in progress: $enc_progress"
            elif [[ -n "$dec_progress" ]]; then
                echo "APFS Decryption Progress: $dec_progress"
                log_action "APFS decryption in progress: $dec_progress"
            else
                echo "No APFS encryption/decryption in progress"
            fi
            ;;
    esac
}

# Check disk information
check_disk_info() {
    echo "=== Disk Information ==="
    
    # Boot disk info
    local boot_disk
    boot_disk=$(diskutil info / | grep "Device Node" | awk '{print $3}')
    echo "Boot Disk: $boot_disk"
    
    # Disk size and usage
    echo "Disk Usage:"
    df -h /
    
    # APFS information (macOS 10.13+)
    if command -v diskutil >/dev/null && diskutil apfs list >/dev/null 2>&1; then
        echo -e "\nAPFS Container Info:"
        diskutil apfs list | grep -E "(Container|Volume|Encryption)"
    fi
}

# Generate compliance report
generate_compliance_report() {
    local report_file="$REPORT_DIR/encryption_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Compliance Report ==="
    
    # Get FileVault status
    local filevault_enabled=false
    local status_detail=""
    
    if sudo fdesetup status 2>/dev/null | grep -q "FileVault is On"; then
        filevault_enabled=true
        status_detail="enabled"
    else
        status_detail="disabled"
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "encryption_compliance",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "hostname": "$(hostname)",
  "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
  "macos_version": "$(sw_vers -productVersion)",
  "encryption": {
    "filevault_enabled": $filevault_enabled,
    "status_detail": "$status_detail",
    "compliance_status": "$([ "$filevault_enabled" == "true" ] && echo "compliant" || echo "non_compliant")",
    "policy_required": $REQUIRE_FILEVAULT
  },
  "disk_info": {
    "boot_disk": "$(diskutil info / | grep "Device Node" | awk '{print $3}')",
    "file_system": "$(diskutil info / | grep "File System" | awk -F: '{print $2}' | xargs)"
  },
  "audit_details": {
    "audit_date": "$(date)",
    "policy_version": "1.0",
    "remediation_required": $([ "$filevault_enabled" != "true" ] && echo "true" || echo "false")
  }
}
EOF
    
    echo "Compliance report saved to: $report_file"
    log_action "Compliance report generated: $report_file"
}

# Remediation actions
perform_remediation() {
    echo "=== Automated Remediation ==="
    
    if [[ "$AUTO_REMEDIATION" != "true" ]]; then
        echo "Auto-remediation disabled in policy"
        return 0
    fi
    
    # Check if FileVault is disabled
    if ! sudo fdesetup status 2>/dev/null | grep -q "FileVault is On"; then
        echo "⚠️  FileVault is disabled - remediation required"
        log_action "REMEDIATION: FileVault encryption is disabled"
        
        echo "Manual remediation steps:"
        echo "1. Open System Preferences > Security & Privacy"
        echo "2. Click the FileVault tab"
        echo "3. Click Turn On FileVault"
        echo "4. Follow the setup wizard"
        echo ""
        echo "Or use MDM to enforce FileVault encryption policy"
        
        # Create remediation ticket (placeholder)
        echo "Creating remediation ticket for device: $(hostname)"
    fi
}

# Main audit function
main() {
    log_action "=== Roundfleet FileVault Audit Started ==="
    
    get_system_info
    check_filevault_status
    local filevault_status=$?
    
    echo ""
    check_encryption_progress
    echo ""
    check_disk_info
    echo ""
    
    if [[ "$COMPLIANCE_REPORTING" == "true" ]]; then
        generate_compliance_report
        echo ""
    fi
    
    if [[ $filevault_status -ne 0 ]]; then
        perform_remediation
    fi
    
    log_action "=== FileVault audit completed with status: $filevault_status ==="
    return $filevault_status
}

# Execute main function
main "$@"

Enterprise Policy Management

Policy Configuration Template

#!/bin/bash

# Create comprehensive encryption policy
cat > /etc/roundfleet/encryption_policy.conf << 'EOF'
# Roundfleet Enterprise Encryption Policy
# Version: 2.0

# Core Requirements
REQUIRE_FILEVAULT=true
ENFORCE_IMMEDIATE_ENCRYPTION=true
ALLOW_PERSONAL_RECOVERY_KEY=false
REQUIRE_INSTITUTIONAL_RECOVERY_KEY=true

# Monitoring Configuration
ALERT_ON_DISABLED=true
MONITOR_PROGRESS=true
PROGRESS_CHECK_INTERVAL=3600  # seconds
COMPLIANCE_REPORTING=true
AUDIT_FREQUENCY=86400  # daily

# Remediation Settings
AUTO_REMEDIATION=false
ESCALATION_THRESHOLD=72  # hours
NOTIFICATION_EMAIL="[email protected]"
HELP_DESK_CONTACT="+1-555-0123"

# Security Policies
MIN_RECOVERY_KEY_LENGTH=24
RECOVERY_KEY_ROTATION_DAYS=90
ENCRYPTION_ALGORITHM="XTS-AES-128"

# Compliance Standards
COMPLIANCE_FRAMEWORKS="SOC2,HIPAA,PCI-DSS"
DATA_CLASSIFICATION_REQUIRED=true
AUDIT_TRAIL_RETENTION_DAYS=2555  # 7 years
EOF

echo "Enterprise encryption policy configured"

Recovery Key Management

#!/bin/bash

# Enterprise recovery key management
manage_recovery_keys() {
    echo "=== Recovery Key Management ==="
    
    # Check if institutional recovery key is set
    local has_institutional_key=false
    if sudo fdesetup list 2>/dev/null | grep -q "institutional"; then
        has_institutional_key=true
        echo "✅ Institutional recovery key configured"
    else
        echo "❌ No institutional recovery key found"
    fi
    
    # Validate recovery key
    if [[ "$has_institutional_key" == "true" ]]; then
        echo "Recovery key validation:"
        sudo fdesetup validaterecovery 2>/dev/null && echo "✅ Recovery key valid" || echo "❌ Recovery key invalid"
    fi
    
    # Escrow recovery key (MDM integration)
    echo "Recovery key escrow status:"
    if system_profiler SPConfigurationProfileDataType | grep -q "FDERecoveryKeyEscrow"; then
        echo "✅ Recovery key escrowed to MDM"
    else
        echo "⚠️  Recovery key not escrowed"
    fi
}

manage_recovery_keys

Monitoring and Alerting

Continuous Monitoring Script

#!/bin/bash

# Continuous FileVault monitoring daemon
DAEMON_NAME="roundfleet-encryption-monitor"
PID_FILE="/var/run/${DAEMON_NAME}.pid"
CHECK_INTERVAL=300  # 5 minutes

# Daemon functions
start_monitoring() {
    if [[ -f "$PID_FILE" ]]; then
        echo "Monitoring daemon already running (PID: $(cat "$PID_FILE"))"
        return 1
    fi
    
    echo "Starting FileVault monitoring daemon..."
    
    # Background monitoring loop
    (
        while true; do
            # Quick status check
            if ! sudo fdesetup status 2>/dev/null | grep -q "FileVault is On"; then
                logger -t "$DAEMON_NAME" "ALERT: FileVault encryption disabled on $(hostname)"
                
                # Send notification (customize for your environment)
                osascript -e 'display notification "FileVault encryption is disabled!" with title "Roundfleet Security Alert"' 2>/dev/null || true
            fi
            
            sleep "$CHECK_INTERVAL"
        done
    ) &
    
    echo $! > "$PID_FILE"
    echo "Monitoring daemon started (PID: $!)"
}

stop_monitoring() {
    if [[ -f "$PID_FILE" ]]; then
        local pid
        pid=$(cat "$PID_FILE")
        kill "$pid" 2>/dev/null
        rm -f "$PID_FILE"
        echo "Monitoring daemon stopped"
    else
        echo "Monitoring daemon not running"
    fi
}

# Execute based on argument
case "${1:-start}" in
    start)
        start_monitoring
        ;;
    stop)
        stop_monitoring
        ;;
    restart)
        stop_monitoring
        sleep 2
        start_monitoring
        ;;
    status)
        if [[ -f "$PID_FILE" ]]; then
            echo "Monitoring daemon running (PID: $(cat "$PID_FILE"))"
        else
            echo "Monitoring daemon not running"
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

Important Security Notes

FileVault Best Practices

  • Enable before deployment - Encrypt devices before user deployment
  • Escrow recovery keys - Use MDM for centralized key management
  • Regular key rotation - Rotate institutional recovery keys periodically
  • Monitor compliance - Continuous monitoring for policy violations
  • Test recovery procedures - Regularly test key recovery processes

Enterprise Considerations

  • Performance impact - Minimal on modern Mac hardware with T2/Apple Silicon
  • Initial encryption time - Can take several hours for large drives
  • Recovery planning - Ensure recovery key availability for support
  • User training - Educate users on encryption benefits and recovery
  • Compliance reporting - Regular audits for regulatory requirements

Apple Silicon Considerations

  • Hardware acceleration - Optimized encryption performance
  • Secure Enclave - Enhanced key protection
  • Progress monitoring limitations - Some monitoring tools may not work
  • Boot security - Additional security features beyond FileVault

Remember to test these scripts thoroughly in your environment before deploying to production devices.

File Size and Storage Analysis on macOS

Master file size analysis and storage management on your Roundfleet devices using powerful disk usage tools. This tutorial covers basic size queries, storage analysis, disk usage monitoring, and advanced storage optimization techniques for effective fleet storage management.

Understanding macOS Storage Analysis

macOS provides several command-line tools for storage analysis:

  • du - Disk usage analysis for files and directories
  • df - File system disk space usage
  • ls - File listing with size information
  • find - Search files by size criteria
  • stat - Detailed file information including size

Basic File and Folder Size Operations

Find Single File Size

#!/bin/bash

# Get size of a specific file
FILE_PATH="/Users/stefan/Desktop/Document.txt"

echo "File size for: $FILE_PATH"
du -h "$FILE_PATH"

echo "File size analysis completed"

Find Folder Size

#!/bin/bash

# Get size of a folder
FOLDER_PATH="/Users/stefan/Desktop/Wallpapers"

echo "Folder size for: $FOLDER_PATH"
du -h "$FOLDER_PATH"

echo "Folder size analysis completed"

Detailed Size Information

#!/bin/bash

# Get detailed size information with options
analyze_size() {
    local target_path="$1"
    
    if [[ ! -e "$target_path" ]]; then
        echo "Error: Path not found: $target_path"
        return 1
    fi
    
    echo "=== Size Analysis for: $target_path ==="
    
    # Basic size
    echo "Total size:"
    du -h "$target_path"
    
    # Size with all files listed
    echo -e "\nDetailed breakdown:"
    du -ah "$target_path" | head -20
    
    # Grand total with summary
    echo -e "\nSummary with total:"
    du -ch "$target_path"
}

# Usage
analyze_size "/Users/stefan/Desktop/Document.txt"

Advanced Storage Analysis

Directory Size Breakdown

#!/bin/bash

# Analyze directory sizes with sorting
directory_analysis() {
    local base_path="$1"
    local max_depth="${2:-1}"
    
    echo "=== Directory Size Analysis: $base_path ==="
    
    # Top-level directory sizes, sorted by size
    echo "Largest directories:"
    du -h -d "$max_depth" "$base_path" 2>/dev/null | sort -hr | head -20
    
    # Count of items
    echo -e "\nItem counts:"
    echo "Files: $(find "$base_path" -type f 2>/dev/null | wc -l)"
    echo "Directories: $(find "$base_path" -type d 2>/dev/null | wc -l)"
    
    # File type analysis
    echo -e "\nFile type distribution:"
    find "$base_path" -type f 2>/dev/null | grep '\.' | rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr | head -10
}

# Usage
directory_analysis "/Users" 2

Large File Detection

#!/bin/bash

# Find large files in directory
find_large_files() {
    local search_path="$1"
    local min_size="${2:-100M}"
    
    echo "=== Large Files Analysis (>$min_size) in: $search_path ==="
    
    # Find large files
    echo "Large files found:"
    find "$search_path" -type f -size +"$min_size" -exec ls -lh {} \; 2>/dev/null | sort -k5 -hr
    
    # Count and total size
    local large_files_count=$(find "$search_path" -type f -size +"$min_size" 2>/dev/null | wc -l)
    echo -e "\nTotal large files: $large_files_count"
    
    if [[ $large_files_count -gt 0 ]]; then
        echo "Total size of large files:"
        find "$search_path" -type f -size +"$min_size" -exec du -ch {} + 2>/dev/null | tail -1
    fi
}

# Usage
find_large_files "/Users" "50M"

Storage Usage by File Type

#!/bin/bash

# Analyze storage usage by file extension
storage_by_type() {
    local search_path="$1"
    
    echo "=== Storage Usage by File Type: $search_path ==="
    
    # Create temporary file for analysis
    local temp_file="/tmp/file_analysis_$$"
    
    # Get all files with extensions and their sizes
    find "$search_path" -type f -name "*.*" -exec sh -c '
        for file; do
            ext=$(echo "$file" | rev | cut -d. -f1 | rev | tr "[:upper:]" "[:lower:]")
            size=$(stat -f%z "$file" 2>/dev/null || echo 0)
            echo "$ext $size"
        done
    ' _ {} + > "$temp_file"
    
    # Summarize by extension
    echo "Top file types by total size:"
    awk '{
        ext_size[$1] += $2
        ext_count[$1]++
    } END {
        for (ext in ext_size) {
            printf "%-10s %15s %10d files\n", ext, ext_size[ext], ext_count[ext]
        }
    }' "$temp_file" | sort -k2 -nr | head -15 | \
    while read ext size count; do
        # Convert bytes to human readable
        if [[ $size -gt 1073741824 ]]; then
            printf "%-10s %10.2f GB %10d files\n" "$ext" $(echo "scale=2; $size/1073741824" | bc) "$count"
        elif [[ $size -gt 1048576 ]]; then
            printf "%-10s %10.2f MB %10d files\n" "$ext" $(echo "scale=2; $size/1048576" | bc) "$count"
        else
            printf "%-10s %10.2f KB %10d files\n" "$ext" $(echo "scale=2; $size/1024" | bc) "$count"
        fi
    done
    
    # Cleanup
    rm -f "$temp_file"
}

# Usage
storage_by_type "/Users"

Disk Space Monitoring

System Disk Usage

#!/bin/bash

# Comprehensive disk usage report
system_disk_report() {
    echo "=== System Disk Usage Report ==="
    
    # File system usage
    echo "File System Usage:"
    df -h
    
    echo -e "\nDisk usage by mount point:"
    df -h | awk 'NR>1 {print $5 " " $1}' | while read output; do
        usage=$(echo $output | awk '{print $1}' | cut -d'%' -f1)
        partition=$(echo $output | awk '{print $2}')
        if [[ $usage -ge 80 ]]; then
            echo "⚠️  $partition: ${usage}% (WARNING)"
        elif [[ $usage -ge 90 ]]; then
            echo "🚨 $partition: ${usage}% (CRITICAL)"
        else
            echo "✅ $partition: ${usage}%"
        fi
    done
    
    # Top directories by size
    echo -e "\nTop directories by size:"
    du -h / 2>/dev/null | sort -hr | head -10
}

# Run system report
system_disk_report

Storage Trend Analysis

#!/bin/bash

# Monitor storage trends over time
storage_trend_monitor() {
    local target_path="$1"
    local log_file="/var/log/roundfleet_storage_trends.log"
    
    echo "=== Storage Trend Monitoring: $target_path ==="
    
    # Current timestamp and size
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local current_size=$(du -sk "$target_path" 2>/dev/null | cut -f1)
    
    # Log current measurement
    echo "$timestamp,$target_path,$current_size" >> "$log_file"
    
    # Show recent trends if log exists
    if [[ -f "$log_file" ]]; then
        echo "Recent storage trends (last 10 measurements):"
        echo "Timestamp                | Path              | Size (KB)    | Change"
        echo "-------------------------|-------------------|--------------|--------"
        
        tail -10 "$log_file" | while IFS=',' read -r time path size; do
            # Calculate change from previous measurement
            printf "%-24s | %-17s | %12s | \n" "$time" "$(basename "$path")" "$size"
        done
        
        # Calculate growth rate
        local first_size=$(head -1 "$log_file" | cut -d',' -f3)
        local growth=$((current_size - first_size))
        local growth_percent=$(echo "scale=2; ($growth * 100) / $first_size" | bc 2>/dev/null || echo "0")
        
        echo -e "\nGrowth since first measurement: ${growth} KB (${growth_percent}%)"
    fi
}

# Usage
storage_trend_monitor "/Users"

Enterprise Storage Management System

#!/bin/bash

# Roundfleet Storage Management Tool
# Comprehensive storage analysis and optimization for fleet devices

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_storage.log"
REPORT_DIR="/etc/roundfleet/reports/storage"
CONFIG_DIR="/etc/roundfleet/storage"
ALERT_DIR="$CONFIG_DIR/alerts"

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

# Storage categories for analysis
declare -A STORAGE_CATEGORIES=(
    ["system_critical"]="/System,/Library,/usr,/bin,/sbin"
    ["user_data"]="/Users,/home"
    ["applications"]="/Applications"
    ["caches"]="/Library/Caches,/Users/*/Library/Caches"
    ["logs"]="/var/log,/Library/Logs,/Users/*/Library/Logs"
    ["downloads"]="/Users/*/Downloads"
    ["documents"]="/Users/*/Documents,/Users/*/Desktop"
    ["media"]="/Users/*/Movies,/Users/*/Music,/Users/*/Pictures"
    ["temporary"]="/tmp,/var/tmp,/Users/*/Library/Application Support/*/Cache"
    ["development"]="/usr/local,/opt,/Users/*/Development"
)

# Storage thresholds and policies
declare -A STORAGE_POLICIES=(
    ["space_warning"]="80,85,90,95"
    ["large_file_threshold"]="100M,500M,1G,5G"
    ["old_file_threshold"]="30,90,180,365"
    ["cache_cleanup_age"]="7,14,30,60"
    ["temp_cleanup_age"]="1,3,7,14"
    ["log_retention_days"]="30,60,90,180"
)

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

# Advanced storage analysis engine
analyze_storage_comprehensive() {
    local target_path="$1"
    local analysis_level="${2:-standard}"
    local category="${3:-general}"
    
    log_action "Starting comprehensive storage analysis: $target_path (Level: $analysis_level)"
    
    if [[ ! -e "$target_path" ]]; then
        log_action "ERROR: Target path does not exist: $target_path"
        return 1
    fi
    
    local report_file="$REPORT_DIR/storage_analysis_$(echo "$target_path" | tr '/' '_')_$(date +%Y%m%d_%H%M%S).json"
    
    # Initialize report
    cat > "$report_file" << EOF
{
    "analysis_info": {
        "target_path": "$target_path",
        "analysis_level": "$analysis_level",
        "category": "$category",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION"
    },
    "storage_metrics": {},
    "file_analysis": {},
    "recommendations": [],
    "alerts": []
}
EOF
    
    # Basic storage metrics
    local total_size_kb=$(du -sk "$target_path" 2>/dev/null | cut -f1)
    local total_files=$(find "$target_path" -type f 2>/dev/null | wc -l)
    local total_dirs=$(find "$target_path" -type d 2>/dev/null | wc -l)
    local largest_file_size=$(find "$target_path" -type f -exec stat -f%z {} \; 2>/dev/null | sort -nr | head -1)
    
    # Update report with basic metrics
    jq --argjson total_size_kb "$total_size_kb" \
       --argjson total_files "$total_files" \
       --argjson total_dirs "$((total_dirs - 1))" \
       --argjson largest_file "$largest_file_size" \
       '.storage_metrics = {
           "total_size_kb": $total_size_kb,
           "total_size_mb": ($total_size_kb / 1024),
           "total_size_gb": ($total_size_kb / 1048576),
           "total_files": $total_files,
           "total_directories": $total_dirs,
           "largest_file_bytes": $largest_file,
           "average_file_size": (if $total_files > 0 then ($total_size_kb * 1024 / $total_files) else 0 end)
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    
    # Perform analysis based on level
    case "$analysis_level" in
        "quick")
            perform_quick_storage_analysis "$target_path" "$report_file"
            ;;
        "standard")
            perform_standard_storage_analysis "$target_path" "$report_file"
            ;;
        "comprehensive")
            perform_comprehensive_storage_analysis "$target_path" "$report_file"
            ;;
        "optimization")
            perform_optimization_analysis "$target_path" "$report_file"
            ;;
        "security")
            perform_security_storage_analysis "$target_path" "$report_file"
            ;;
    esac
    
    log_action "Storage analysis completed: $report_file"
    echo "$report_file"
}

# Quick storage analysis
perform_quick_storage_analysis() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Performing quick storage analysis..."
    
    # Top-level directory sizes
    local dir_sizes=$(du -h -d 1 "$target_path" 2>/dev/null | sort -hr | head -10)
    
    # Large files (>100MB)
    local large_files=$(find "$target_path" -type f -size +100M 2>/dev/null | head -10)
    
    # Update report
    jq --arg dir_sizes "$dir_sizes" \
       --arg large_files "$large_files" \
       '.file_analysis.quick = {
           "directory_sizes": $dir_sizes,
           "large_files_100mb": $large_files
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Standard storage analysis
perform_standard_storage_analysis() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Performing standard storage analysis..."
    
    # File age analysis
    local recent_files=$(find "$target_path" -type f -mtime -7 2>/dev/null | wc -l)
    local old_files=$(find "$target_path" -type f -mtime +365 2>/dev/null | wc -l)
    
    # File size distribution
    local small_files=$(find "$target_path" -type f -size -1k 2>/dev/null | wc -l)
    local medium_files=$(find "$target_path" -type f -size +1k -size -1M 2>/dev/null | wc -l)
    local large_files=$(find "$target_path" -type f -size +1M -size -100M 2>/dev/null | wc -l)
    local huge_files=$(find "$target_path" -type f -size +100M 2>/dev/null | wc -l)
    
    # Empty files and directories
    local empty_files=$(find "$target_path" -type f -empty 2>/dev/null | wc -l)
    local empty_dirs=$(find "$target_path" -type d -empty 2>/dev/null | wc -l)
    
    # Update report
    jq --argjson recent_files "$recent_files" \
       --argjson old_files "$old_files" \
       --argjson small_files "$small_files" \
       --argjson medium_files "$medium_files" \
       --argjson large_files "$large_files" \
       --argjson huge_files "$huge_files" \
       --argjson empty_files "$empty_files" \
       --argjson empty_dirs "$empty_dirs" \
       '.file_analysis.standard = {
           "file_age": {
               "recent_files": $recent_files,
               "old_files": $old_files
           },
           "file_sizes": {
               "small_1kb": $small_files,
               "medium_1kb_1mb": $medium_files,
               "large_1mb_100mb": $large_files,
               "huge_100mb_plus": $huge_files
           },
           "empty_items": {
               "empty_files": $empty_files,
               "empty_directories": $empty_dirs
           }
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Comprehensive storage analysis
perform_comprehensive_storage_analysis() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Performing comprehensive storage analysis..."
    
    # Duplicate file detection
    local duplicates_temp="/tmp/duplicates_$$"
    find "$target_path" -type f -exec md5 {} \; 2>/dev/null | sort | uniq -d -w 32 > "$duplicates_temp"
    local duplicate_count=$(wc -l < "$duplicates_temp")
    
    # File extension analysis
    local extensions_temp="/tmp/extensions_$$"
    find "$target_path" -type f -name "*.*" 2>/dev/null | rev | cut -d. -f1 | rev | sort | uniq -c | sort -nr > "$extensions_temp"
    
    # Access pattern analysis
    local never_accessed=$(find "$target_path" -type f -atime +365 2>/dev/null | wc -l)
    local recently_accessed=$(find "$target_path" -type f -atime -1 2>/dev/null | wc -l)
    
    # Directory depth analysis
    local max_depth=$(find "$target_path" -type d 2>/dev/null | awk -F/ '{print NF}' | sort -n | tail -1)
    local current_depth=$(echo "$target_path" | tr -cd '/' | wc -c)
    local relative_depth=$((max_depth - current_depth))
    
    # Update report
    jq --argjson duplicate_count "$duplicate_count" \
       --argjson never_accessed "$never_accessed" \
       --argjson recently_accessed "$recently_accessed" \
       --argjson max_depth "$relative_depth" \
       '.file_analysis.comprehensive = {
           "duplicates": {
               "duplicate_file_sets": $duplicate_count
           },
           "access_patterns": {
               "never_accessed": $never_accessed,
               "recently_accessed": $recently_accessed
           },
           "structure": {
               "maximum_depth": $max_depth
           }
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    
    # Cleanup temp files
    rm -f "$duplicates_temp" "$extensions_temp"
}

# Optimization analysis
perform_optimization_analysis() {
    local target_path="$1"
    local report_file="$2"
    
    echo "Performing optimization analysis..."
    
    # Cache files
    local cache_files=$(find "$target_path" -path "*/Cache*" -o -name "*cache*" 2>/dev/null | wc -l)
    local cache_size=$(find "$target_path" -path "*/Cache*" -o -name "*cache*" -exec du -sk {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
    
    # Log files
    local log_files=$(find "$target_path" -name "*.log" 2>/dev/null | wc -l)
    local log_size=$(find "$target_path" -name "*.log" -exec du -sk {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
    
    # Temporary files
    local temp_files=$(find "$target_path" -name "*.tmp" -o -name "*.temp" -o -path "*/tmp/*" 2>/dev/null | wc -l)
    local temp_size=$(find "$target_path" -name "*.tmp" -o -name "*.temp" -o -path "*/tmp/*" -exec du -sk {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
    
    # Backup files
    local backup_files=$(find "$target_path" -name "*.bak" -o -name "*~" -o -name "*.backup" 2>/dev/null | wc -l)
    local backup_size=$(find "$target_path" -name "*.bak" -o -name "*~" -o -name "*.backup" -exec du -sk {} + 2>/dev/null | awk '{sum+=$1} END {print sum+0}')
    
    # Potential savings calculation
    local total_cleanup_kb=$((cache_size + log_size + temp_size + backup_size))
    local total_cleanup_mb=$((total_cleanup_kb / 1024))
    
    # Generate recommendations
    local recommendations=()
    [[ $cache_size -gt 102400 ]] && recommendations+=("Consider cleaning cache files (${cache_size} KB)")
    [[ $log_size -gt 51200 ]] && recommendations+=("Archive or clean old log files (${log_size} KB)")
    [[ $temp_size -gt 10240 ]] && recommendations+=("Remove temporary files (${temp_size} KB)")
    [[ $backup_size -gt 102400 ]] && recommendations+=("Review backup file retention (${backup_size} KB)")
    
    # Update report
    jq --argjson cache_files "$cache_files" \
       --argjson cache_size "$cache_size" \
       --argjson log_files "$log_files" \
       --argjson log_size "$log_size" \
       --argjson temp_files "$temp_files" \
       --argjson temp_size "$temp_size" \
       --argjson backup_files "$backup_files" \
       --argjson backup_size "$backup_size" \
       --argjson total_cleanup "$total_cleanup_kb" \
       --argjson recommendations "$(printf '%s\n' "${recommendations[@]}" | jq -R . | jq -s .)" \
       '.file_analysis.optimization = {
           "cache_files": {"count": $cache_files, "size_kb": $cache_size},
           "log_files": {"count": $log_files, "size_kb": $log_size},
           "temp_files": {"count": $temp_files, "size_kb": $temp_size},
           "backup_files": {"count": $backup_files, "size_kb": $backup_size},
           "potential_savings_kb": $total_cleanup,
           "potential_savings_mb": ($total_cleanup / 1024)
       } | .recommendations = $recommendations' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Fleet storage management
manage_fleet_storage() {
    local action="$1"
    local target_pattern="$2"
    local threshold="$3"
    
    log_action "Fleet storage management: $action"
    
    case "$action" in
        "audit")
            audit_fleet_storage "$target_pattern"
            ;;
        "cleanup")
            cleanup_fleet_storage "$target_pattern" "$threshold"
            ;;
        "monitor")
            monitor_fleet_storage
            ;;
        "report")
            generate_fleet_storage_report
            ;;
    esac
}

# Generate fleet storage report
generate_fleet_storage_report() {
    local fleet_report="$REPORT_DIR/fleet_storage_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "Generating fleet storage report..."
    
    # System overview
    local total_disk_space=$(df -k / | awk 'NR==2 {print $2}')
    local used_disk_space=$(df -k / | awk 'NR==2 {print $3}')
    local available_disk_space=$(df -k / | awk 'NR==2 {print $4}')
    local disk_usage_percent=$(df / | awk 'NR==2 {print $5}' | sed 's/%//')
    
    cat > "$fleet_report" << EOF
{
    "fleet_storage_report": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "system_overview": {
            "total_disk_kb": $total_disk_space,
            "used_disk_kb": $used_disk_space,
            "available_disk_kb": $available_disk_space,
            "usage_percent": $disk_usage_percent
        },
        "category_analysis": {},
        "alerts": [],
        "recommendations": []
    }
}
EOF
    
    # Analyze each storage category
    for category in "${!STORAGE_CATEGORIES[@]}"; do
        echo "Analyzing category: $category"
        IFS=',' read -ra PATHS <<< "${STORAGE_CATEGORIES[$category]}"
        local category_size=0
        local category_files=0
        
        for path in "${PATHS[@]}"; do
            if [[ -d "$path" ]]; then
                local path_size=$(du -sk "$path" 2>/dev/null | cut -f1)
                local path_files=$(find "$path" -type f 2>/dev/null | wc -l)
                category_size=$((category_size + path_size))
                category_files=$((category_files + path_files))
            fi
        done
        
        # Update report with category data
        jq --arg category "$category" \
           --argjson size "$category_size" \
           --argjson files "$category_files" \
           '.fleet_storage_report.category_analysis[$category] = {
               "size_kb": $size,
               "file_count": $files,
               "size_mb": ($size / 1024),
               "size_gb": ($size / 1048576)
           }' "$fleet_report" > "${fleet_report}.tmp" && mv "${fleet_report}.tmp" "$fleet_report"
    done
    
    # Generate alerts based on thresholds
    local alerts=()
    if [[ $disk_usage_percent -gt 90 ]]; then
        alerts+=("CRITICAL: Disk usage above 90% ($disk_usage_percent%)")
    elif [[ $disk_usage_percent -gt 80 ]]; then
        alerts+=("WARNING: Disk usage above 80% ($disk_usage_percent%)")
    fi
    
    # Add alerts to report
    if [[ ${#alerts[@]} -gt 0 ]]; then
        jq --argjson alerts "$(printf '%s\n' "${alerts[@]}" | jq -R . | jq -s .)" \
           '.fleet_storage_report.alerts = $alerts' "$fleet_report" > "${fleet_report}.tmp" && mv "${fleet_report}.tmp" "$fleet_report"
    fi
    
    log_action "Fleet storage report generated: $fleet_report"
    echo "$fleet_report"
}

# Main execution function
main() {
    local action="${1:-analyze}"
    local target="${2:-/Users}"
    local level="${3:-standard}"
    local options="${4:-}"
    
    log_action "=== Roundfleet Storage Management Started ==="
    log_action "Action: $action, Target: $target, Level: $level"
    
    case "$action" in
        "analyze")
            analyze_storage_comprehensive "$target" "$level"
            ;;
        "size")
            echo "File/Folder size:"
            du -h "$target"
            ;;
        "fleet")
            manage_fleet_storage "$level" "$target" "$options"
            ;;
        "report")
            generate_fleet_storage_report
            ;;
        "help")
            echo "Usage: $0 [action] [target] [level] [options]"
            echo "Actions:"
            echo "  analyze <path> [level] - Comprehensive storage analysis"
            echo "  size <path> - Simple size check"
            echo "  fleet <action> [pattern] [threshold] - Fleet management"
            echo "  report - Generate fleet storage report"
            echo "  help - Show this help"
            echo ""
            echo "Analysis levels: quick, standard, comprehensive, optimization, security"
            echo "Fleet actions: audit, cleanup, monitor, report"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            exit 1
            ;;
    esac
    
    log_action "=== Storage management completed ==="
}

# Execute main function
main "$@"

Common Storage Analysis Tasks

Directory Comparison

#!/bin/bash

# Compare sizes of multiple directories
compare_directories() {
    local directories=("$@")
    
    echo "=== Directory Size Comparison ==="
    printf "%-40s %15s %15s\n" "Directory" "Size" "Files"
    echo "--------------------------------------------------------------------------------"
    
    for dir in "${directories[@]}"; do
        if [[ -d "$dir" ]]; then
            local size=$(du -sh "$dir" 2>/dev/null | cut -f1)
            local files=$(find "$dir" -type f 2>/dev/null | wc -l)
            printf "%-40s %15s %15d\n" "$dir" "$size" "$files"
        else
            printf "%-40s %15s %15s\n" "$dir" "N/A" "N/A"
        fi
    done
}

# Usage
compare_directories "/Users/stefan/Documents" "/Users/stefan/Downloads" "/Users/stefan/Desktop"

Storage Growth Tracking

#!/bin/bash

# Track storage growth over time
track_storage_growth() {
    local target_path="$1"
    local log_file="/var/log/storage_growth.csv"
    
    # Create header if file doesn't exist
    if [[ ! -f "$log_file" ]]; then
        echo "timestamp,path,size_kb,files,directories" > "$log_file"
    fi
    
    # Get current metrics
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local size_kb=$(du -sk "$target_path" 2>/dev/null | cut -f1)
    local files=$(find "$target_path" -type f 2>/dev/null | wc -l)
    local dirs=$(find "$target_path" -type d 2>/dev/null | wc -l)
    
    # Log current measurement
    echo "$timestamp,$target_path,$size_kb,$files,$dirs" >> "$log_file"
    
    echo "Storage growth logged for: $target_path"
    echo "Current size: $(echo "scale=2; $size_kb/1024" | bc) MB"
    echo "Files: $files, Directories: $dirs"
}

# Usage
track_storage_growth "/Users/stefan"

Cleanup Recommendations

#!/bin/bash

# Generate cleanup recommendations
generate_cleanup_recommendations() {
    local target_path="$1"
    
    echo "=== Cleanup Recommendations for: $target_path ==="
    
    # Old downloads
    local old_downloads=$(find "$target_path" -path "*/Downloads/*" -type f -mtime +30 2>/dev/null | wc -l)
    if [[ $old_downloads -gt 0 ]]; then
        echo "📁 Found $old_downloads files in Downloads older than 30 days"
    fi
    
    # Large cache files
    local cache_size=$(find "$target_path" -path "*/Cache*" -type f -size +10M 2>/dev/null | wc -l)
    if [[ $cache_size -gt 0 ]]; then
        echo "🗂️  Found $cache_size large cache files (>10MB)"
    fi
    
    # Duplicate files
    local duplicates=$(find "$target_path" -type f -exec md5 {} \; 2>/dev/null | sort | uniq -d -w 32 | wc -l)
    if [[ $duplicates -gt 0 ]]; then
        echo "📄 Found approximately $duplicates duplicate files"
    fi
    
    # Empty directories
    local empty_dirs=$(find "$target_path" -type d -empty 2>/dev/null | wc -l)
    if [[ $empty_dirs -gt 0 ]]; then
        echo "📂 Found $empty_dirs empty directories"
    fi
    
    # Log files
    local large_logs=$(find "$target_path" -name "*.log" -size +50M 2>/dev/null | wc -l)
    if [[ $large_logs -gt 0 ]]; then
        echo "📋 Found $large_logs large log files (>50MB)"
    fi
    
    echo -e "\n💡 Consider running cleanup operations for these items"
}

# Usage
generate_cleanup_recommendations "/Users"

Important Notes

  • File paths with spaces - Use quotes or escape characters: du -h "/path/with spaces"
  • Permission requirements - Some directories require admin access
  • Performance impact - Large directory scans can be resource-intensive
  • Regular monitoring - Set up automated storage monitoring for fleet management
  • Backup before cleanup - Always backup important data before cleanup operations
  • Test scripts on sample directories before fleet-wide deployment

File Protection on macOS

Protect critical files and applications across your Roundfleet devices using advanced file protection techniques, immutable flags, and enterprise security policies. This tutorial provides comprehensive tools for implementing organizational file security standards.

Understanding macOS File Protection Methods

macOS offers several file protection mechanisms:

  • Immutable Flags - System-level protection preventing modification or deletion
  • File Permissions - User and group-based access controls
  • Extended Attributes - Additional metadata for security enforcement
  • System Integrity Protection (SIP) - Built-in protection for system files

Basic File Protection Commands

Lock Single File

#!/bin/bash

# Lock a file using immutable flag
FILE_PATH="/Applications/WhatsApp.app"

chflags schg "$FILE_PATH"
echo "File locked: $FILE_PATH"

Unlock Single File

#!/bin/bash

# Unlock a file by removing immutable flag
FILE_PATH="/Applications/WhatsApp.app"

chflags noschg "$FILE_PATH"
echo "File unlocked: $FILE_PATH"

Check File Protection Status

#!/bin/bash

# Check if file is protected
FILE_PATH="/Applications/WhatsApp.app"

if ls -lO "$FILE_PATH" | grep -q "schg"; then
    echo "File is protected: $FILE_PATH"
else
    echo "File is not protected: $FILE_PATH"
fi

Enterprise File Protection System

#!/bin/bash

# Roundfleet Enterprise File Protection System
# Comprehensive file security and protection management

# Configuration
ROUNDFLEET_DIR="/etc/roundfleet"
POLICIES_DIR="$ROUNDFLEET_DIR/file_policies"
REPORTS_DIR="$ROUNDFLEET_DIR/reports"
COMPLIANCE_DIR="$ROUNDFLEET_DIR/compliance"
AUDIT_DIR="$ROUNDFLEET_DIR/audit"
LOG_FILE="/var/log/roundfleet_file_protection.log"
BACKUP_DIR="$ROUNDFLEET_DIR/backups"

# Create directory structure
create_directories() {
    local dirs=("$ROUNDFLEET_DIR" "$POLICIES_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$BACKUP_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"
}

# File Categories for Enterprise Protection
declare -A FILE_CATEGORIES=(
    ["critical_apps"]="/Applications/System Preferences.app,/Applications/Terminal.app,/Applications/Utilities"
    ["business_apps"]="/Applications/Microsoft Office,/Applications/Slack.app,/Applications/Zoom.app"
    ["system_configs"]="/etc/hosts,/etc/sudoers,/etc/ssh/sshd_config"
    ["security_tools"]="/Applications/1Password.app,/Applications/Keychain Access.app"
    ["development_tools"]="/Applications/Xcode.app,/Applications/Visual Studio Code.app"
    ["admin_utilities"]="/Applications/Activity Monitor.app,/Applications/Console.app"
)

# Protection Levels
declare -A PROTECTION_LEVELS=(
    ["maximum"]="schg,uappnd,uchg"        # System immutable, user append-only, user immutable
    ["high"]="schg,uchg"                  # System immutable, user immutable
    ["moderate"]="uchg"                   # User immutable only
    ["minimal"]="uappnd"                  # User append-only
    ["readonly"]="ro"                     # Read-only access
)

# Security Policies
declare -A SECURITY_POLICIES=(
    ["enterprise_lockdown"]="critical_apps:maximum,business_apps:high,system_configs:maximum,security_tools:high"
    ["standard_protection"]="critical_apps:high,system_configs:high,security_tools:moderate"
    ["development_safe"]="critical_apps:moderate,system_configs:high,development_tools:minimal"
    ["minimal_security"]="system_configs:moderate,security_tools:minimal"
    ["maintenance_mode"]="system_configs:readonly"
)

# Apply protection to file or directory
protect_file() {
    local file_path="$1"
    local protection_level="$2"
    local policy="$3"
    
    if [[ ! -e "$file_path" ]]; then
        log_action "ERROR: File not found: $file_path"
        return 1
    fi
    
    # Backup current flags
    local current_flags=$(ls -lO "$file_path" 2>/dev/null | awk '{print $5}' || echo "none")
    echo "$file_path:$current_flags:$(date)" >> "$BACKUP_DIR/file_flags_backup.log"
    
    # Apply protection based on level
    local flags="${PROTECTION_LEVELS[$protection_level]}"
    if [[ -z "$flags" ]]; then
        log_action "ERROR: Unknown protection level: $protection_level"
        return 1
    fi
    
    # Split flags and apply each one
    IFS=',' read -ra flag_array <<< "$flags"
    for flag in "${flag_array[@]}"; do
        if chflags "$flag" "$file_path" 2>/dev/null; then
            log_action "Applied protection flag '$flag' to: $file_path (Policy: $policy)"
        else
            log_action "ERROR: Failed to apply flag '$flag' to: $file_path"
        fi
    done
    
    # Set restrictive permissions if needed
    if [[ "$protection_level" == "maximum" || "$protection_level" == "high" ]]; then
        chmod 644 "$file_path" 2>/dev/null
        log_action "Set restrictive permissions for: $file_path"
    fi
    
    # Save protection metadata
    echo "file=$file_path,protection=$protection_level,policy=$policy,timestamp=$(date),user=$(whoami)" >> "$POLICIES_DIR/applied_protections.log"
}

# Remove protection from file
unprotect_file() {
    local file_path="$1"
    local reason="$2"
    
    if [[ ! -e "$file_path" ]]; then
        log_action "ERROR: File not found: $file_path"
        return 1
    fi
    
    # Remove all common protection flags
    local flags_to_remove=("schg" "uchg" "uappnd" "ro")
    
    for flag in "${flags_to_remove[@]}"; do
        if chflags "no$flag" "$file_path" 2>/dev/null; then
            log_action "Removed protection flag '$flag' from: $file_path (Reason: $reason)"
        fi
    done
    
    # Restore standard permissions
    if [[ -f "$file_path" ]]; then
        chmod 644 "$file_path" 2>/dev/null
    elif [[ -d "$file_path" ]]; then
        chmod 755 "$file_path" 2>/dev/null
    fi
    
    log_action "File unprotected: $file_path (Reason: $reason)"
}

# Apply protection to file category
protect_category() {
    local category="$1"
    local protection_level="$2"
    local policy="$3"
    
    if [[ -z "${FILE_CATEGORIES[$category]}" ]]; then
        log_action "ERROR: Unknown file category: $category"
        return 1
    fi
    
    log_action "Protecting category: $category with level: $protection_level (Policy: $policy)"
    
    # Split comma-separated file paths
    IFS=',' read -ra files <<< "${FILE_CATEGORIES[$category]}"
    
    for file_path in "${files[@]}"; do
        # Handle wildcard patterns
        if [[ "$file_path" == *"*"* ]]; then
            # Use find for pattern matching
            find "${file_path%/*}" -name "${file_path##*/}" 2>/dev/null | while read -r found_file; do
                protect_file "$found_file" "$protection_level" "$policy"
            done
        else
            protect_file "$file_path" "$protection_level" "$policy"
        fi
    done
}

# Apply comprehensive security policy
apply_security_policy() {
    local policy="$1"
    
    if [[ -z "${SECURITY_POLICIES[$policy]}" ]]; then
        log_action "ERROR: Unknown security policy: $policy"
        return 1
    fi
    
    log_action "Applying security policy: $policy"
    
    # Parse policy string: "category:level,category:level"
    IFS=',' read -ra policy_items <<< "${SECURITY_POLICIES[$policy]}"
    
    for item in "${policy_items[@]}"; do
        IFS=':' read -ra parts <<< "$item"
        local category="${parts[0]}"
        local protection_level="${parts[1]}"
        
        protect_category "$category" "$protection_level" "$policy"
    done
    
    log_action "Security policy '$policy' applied successfully"
    
    # Generate compliance report
    generate_compliance_report "$policy"
}

# Bulk file protection operations
bulk_protect_files() {
    local file_list="$1"
    local protection_level="$2"
    local policy="$3"
    
    if [[ ! -f "$file_list" ]]; then
        log_action "ERROR: File list not found: $file_list"
        return 1
    fi
    
    log_action "Starting bulk protection operation from list: $file_list"
    local protected_count=0
    local failed_count=0
    
    while IFS= read -r file_path; do
        [[ -z "$file_path" || "$file_path" =~ ^#.*$ ]] && continue
        
        if protect_file "$file_path" "$protection_level" "$policy"; then
            ((protected_count++))
        else
            ((failed_count++))
        fi
    done < "$file_list"
    
    log_action "Bulk protection completed: $protected_count protected, $failed_count failed"
}

# Critical system file protection
protect_system_files() {
    local protection_mode="$1"
    
    log_action "Applying system file protection: $protection_mode"
    
    # Define critical system files
    local critical_files=(
        "/etc/hosts"
        "/etc/sudoers"
        "/etc/ssh/sshd_config"
        "/etc/passwd"
        "/etc/group"
        "/System/Library/LaunchDaemons"
        "/Library/LaunchDaemons"
        "/usr/bin/sudo"
        "/bin/sh"
        "/bin/bash"
    )
    
    case "$protection_mode" in
        "lockdown")
            for file in "${critical_files[@]}"; do
                if [[ -e "$file" ]]; then
                    protect_file "$file" "maximum" "system_lockdown"
                fi
            done
            ;;
        "standard")
            for file in "${critical_files[@]}"; do
                if [[ -e "$file" ]]; then
                    protect_file "$file" "high" "system_standard"
                fi
            done
            ;;
        "minimal")
            for file in "${critical_files[@]}"; do
                if [[ -e "$file" ]]; then
                    protect_file "$file" "moderate" "system_minimal"
                fi
            done
            ;;
    esac
    
    log_action "System file protection applied: $protection_mode"
}

# File integrity monitoring
monitor_file_integrity() {
    local monitoring_mode="$1"
    local monitor_file="$POLICIES_DIR/integrity_monitor.log"
    
    log_action "Starting file integrity monitoring: $monitoring_mode"
    
    # Get list of protected files
    local protected_files=()
    if [[ -f "$POLICIES_DIR/applied_protections.log" ]]; then
        while IFS=',' read -r entry; do
            if [[ "$entry" =~ file=([^,]+) ]]; then
                protected_files+=("${BASH_REMATCH[1]}")
            fi
        done < "$POLICIES_DIR/applied_protections.log"
    fi
    
    # Monitor files for changes
    for file in "${protected_files[@]}"; do
        if [[ -e "$file" ]]; then
            local current_hash=$(shasum -a 256 "$file" 2>/dev/null | cut -d' ' -f1)
            local current_flags=$(ls -lO "$file" 2>/dev/null | awk '{print $5}' || echo "none")
            local timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
            
            echo "$timestamp:$file:$current_hash:$current_flags" >> "$monitor_file"
        fi
    done
    
    log_action "File integrity monitoring completed: $monitoring_mode"
}

# Emergency unlock procedures
emergency_unlock() {
    local reason="$1"
    local unlock_scope="$2"
    
    log_action "EMERGENCY UNLOCK INITIATED - Reason: $reason, Scope: $unlock_scope"
    
    case "$unlock_scope" in
        "all")
            # Unlock all protected files
            if [[ -f "$POLICIES_DIR/applied_protections.log" ]]; then
                while IFS=',' read -r entry; do
                    if [[ "$entry" =~ file=([^,]+) ]]; then
                        unprotect_file "${BASH_REMATCH[1]}" "emergency_unlock"
                    fi
                done < "$POLICIES_DIR/applied_protections.log"
            fi
            ;;
        "system")
            # Unlock only system files
            local system_files=("/etc/hosts" "/etc/sudoers" "/etc/ssh/sshd_config")
            for file in "${system_files[@]}"; do
                if [[ -e "$file" ]]; then
                    unprotect_file "$file" "emergency_system_unlock"
                fi
            done
            ;;
        "applications")
            # Unlock application files
            find /Applications -name "*.app" -exec chflags noschg {} \; 2>/dev/null
            log_action "Emergency unlock completed for applications"
            ;;
    esac
    
    # Create emergency unlock record
    echo "emergency_unlock:$reason:$unlock_scope:$(date):$(whoami)" >> "$AUDIT_DIR/emergency_operations.log"
    log_action "Emergency unlock completed: $unlock_scope"
}

# Generate comprehensive compliance report
generate_compliance_report() {
    local policy="$1"
    local report_file="$REPORTS_DIR/file_protection_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    local protected_files_count=0
    local total_files_checked=0
    
    # Count protected files
    if [[ -f "$POLICIES_DIR/applied_protections.log" ]]; then
        protected_files_count=$(wc -l < "$POLICIES_DIR/applied_protections.log")
    fi
    
    # Count total files in categories
    for category in "${!FILE_CATEGORIES[@]}"; do
        IFS=',' read -ra files <<< "${FILE_CATEGORIES[$category]}"
        total_files_checked=$((total_files_checked + ${#files[@]}))
    done
    
    cat > "$report_file" << EOF
{
  "report_metadata": {
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "policy_applied": "$policy",
    "report_version": "1.0"
  },
  "file_protection_status": {
    "protected_files_count": $protected_files_count,
    "total_files_checked": $total_files_checked,
    "protection_coverage": $(echo "scale=2; $protected_files_count * 100 / $total_files_checked" | bc -l 2>/dev/null || echo "0"),
    "emergency_unlocks_recorded": $([ -f "$AUDIT_DIR/emergency_operations.log" ] && wc -l < "$AUDIT_DIR/emergency_operations.log" || echo "0")
  },
  "security_policy": {
    "name": "$policy",
    "categories_protected": $(echo "${!FILE_CATEGORIES[@]}" | wc -w),
    "compliance_frameworks": ["SOX", "HIPAA", "NIST", "ISO27001", "PCI-DSS"]
  },
  "system_status": {
    "sip_enabled": $(csrutil status | grep -q "enabled" && echo "true" || echo "false"),
    "gatekeeper_enabled": $(spctl --status | grep -q "enabled" && echo "true" || echo "false"),
    "filevault_enabled": $(fdesetup status | grep -q "On" && echo "true" || echo "false"),
    "backup_available": $([ -f "$BACKUP_DIR/file_flags_backup.log" ] && echo "true" || echo "false")
  },
  "integrity_monitoring": {
    "active": $([ -f "$POLICIES_DIR/integrity_monitor.log" ] && echo "true" || echo "false"),
    "last_check": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "monitored_files": $([ -f "$POLICIES_DIR/integrity_monitor.log" ] && wc -l < "$POLICIES_DIR/integrity_monitor.log" || echo "0")
  }
}
EOF
    
    log_action "Compliance report generated: $report_file"
    echo "Report saved to: $report_file"
}

# Health check and validation
perform_health_check() {
    echo "=== Roundfleet File Protection Health Check ==="
    
    # Check system integrity protection
    local sip_status=$(csrutil status 2>/dev/null || echo "Unknown")
    echo "✓ System Integrity Protection: $sip_status"
    
    # Check protected files
    local protected_count=0
    if [[ -f "$POLICIES_DIR/applied_protections.log" ]]; then
        protected_count=$(wc -l < "$POLICIES_DIR/applied_protections.log")
    fi
    echo "✓ Protected files: $protected_count"
    
    # Check critical system files
    local critical_protected=0
    local critical_files=("/etc/hosts" "/etc/sudoers" "/etc/ssh/sshd_config")
    for file in "${critical_files[@]}"; do
        if [[ -e "$file" ]] && ls -lO "$file" | grep -q "schg"; then
            ((critical_protected++))
        fi
    done
    echo "✓ Critical system files protected: $critical_protected/${#critical_files[@]}"
    
    # Check backup availability
    if [[ -f "$BACKUP_DIR/file_flags_backup.log" ]]; then
        local backup_entries=$(wc -l < "$BACKUP_DIR/file_flags_backup.log")
        echo "✓ Backup entries: $backup_entries"
    else
        echo "○ No backup records found"
    fi
    
    # Check integrity monitoring
    if [[ -f "$POLICIES_DIR/integrity_monitor.log" ]]; then
        local monitor_entries=$(wc -l < "$POLICIES_DIR/integrity_monitor.log")
        echo "✓ Integrity monitoring entries: $monitor_entries"
    else
        echo "○ No integrity monitoring active"
    fi
    
    # Check for emergency operations
    if [[ -f "$AUDIT_DIR/emergency_operations.log" ]]; then
        local emergency_count=$(wc -l < "$AUDIT_DIR/emergency_operations.log")
        echo "⚠️  Emergency operations recorded: $emergency_count"
    else
        echo "✓ No emergency operations recorded"
    fi
}

# 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 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 file protection policy: $policy

# Create directories
mkdir -p /etc/roundfleet/{file_policies,reports,compliance,audit,backups}

# Apply the policy (simplified for remote execution)
$(declare -p FILE_CATEGORIES)
$(declare -p PROTECTION_LEVELS)
$(declare -p SECURITY_POLICIES)
$(type apply_security_policy | sed '1d')

apply_security_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
        "apply_policy")
            apply_security_policy "$2"
            ;;
        "protect_file")
            protect_file "$2" "${3:-moderate}" "manual"
            ;;
        "unprotect_file")
            unprotect_file "$2" "${3:-manual_unlock}"
            ;;
        "protect_category")
            protect_category "$2" "${3:-moderate}" "manual"
            ;;
        "bulk_protect")
            bulk_protect_files "$2" "${3:-moderate}" "bulk_operation"
            ;;
        "protect_system")
            protect_system_files "${2:-standard}"
            ;;
        "monitor_integrity")
            monitor_file_integrity "${2:-standard}"
            ;;
        "emergency_unlock")
            emergency_unlock "${2:-manual}" "${3:-all}"
            ;;
        "health_check")
            perform_health_check
            ;;
        "report")
            generate_compliance_report "${2:-manual}"
            ;;
        "deploy")
            deploy_to_fleet "$2" "$3"
            ;;
        "help"|*)
            echo "Roundfleet Enterprise File Protection System"
            echo ""
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  apply_policy <policy>           - Apply security policy (enterprise_lockdown|standard_protection|development_safe|minimal_security|maintenance_mode)"
            echo "  protect_file <path> [level]     - Protect single file (maximum|high|moderate|minimal|readonly)"
            echo "  unprotect_file <path> [reason]  - Remove protection from file"
            echo "  protect_category <category> [level] - Protect file category (critical_apps|business_apps|system_configs|security_tools|development_tools|admin_utilities)"
            echo "  bulk_protect <file_list> [level] - Protect files from list"
            echo "  protect_system [mode]           - Protect system files (lockdown|standard|minimal)"
            echo "  monitor_integrity [mode]        - Monitor file integrity (standard|strict)"
            echo "  emergency_unlock <reason> [scope] - Emergency unlock (all|system|applications)"
            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 apply_policy enterprise_lockdown"
            echo "  $0 protect_file /Applications/Terminal.app maximum"
            echo "  $0 protect_system lockdown"
            echo "  $0 emergency_unlock 'maintenance required' system"
            echo "  $0 health_check"
            ;;
    esac
}

# Execute main function
main "$@"

Protection Levels Explained

LevelDescriptionFlags AppliedUse Case
MaximumComplete system protectionschg, uappnd, uchgCritical system files
HighStrong user protectionschg, uchgImportant applications
ModerateStandard user protectionuchgBusiness applications
MinimalBasic append protectionuappndLog files, databases
Read-onlyPrevent modificationsroConfiguration templates

File Protection Use Cases

Protect Critical Applications

# Protect system utilities from modification
./file_protection.sh protect_category critical_apps maximum

# Protect business applications
./file_protection.sh protect_category business_apps high

System Configuration Protection

# Lock down system configuration files
./file_protection.sh protect_system lockdown

# Standard system protection
./file_protection.sh protect_system standard

Development Environment Safety

# Apply development-safe policy
./file_protection.sh apply_policy development_safe

# Protect development tools with minimal restrictions
./file_protection.sh protect_category development_tools minimal

Emergency Procedures

Complete System Unlock

# Emergency unlock all files
./file_protection.sh emergency_unlock "critical_maintenance" all

# Unlock only system files
./file_protection.sh emergency_unlock "system_update" system

File Recovery

# Check protection status
ls -lO /Applications/Terminal.app

# Remove specific protection
./file_protection.sh unprotect_file /Applications/Terminal.app "maintenance"

Important Security Considerations

  • System Integrity Protection (SIP) provides additional layer beyond file flags
  • Root privileges required for system immutable flags (schg)
  • Backup protection state before making changes
  • Emergency procedures should be tested and documented
  • File integrity monitoring helps detect unauthorized changes

Compliance and Auditing

The enterprise system provides comprehensive audit trails for:

  • SOX Compliance - Financial data protection requirements
  • HIPAA Requirements - Healthcare information security
  • PCI-DSS Standards - Payment card industry data security
  • NIST Framework - Cybersecurity standards compliance
  • ISO 27001 - Information security management

Testing and Validation

Before enterprise deployment:

  1. Test protection levels on non-critical files first
  2. Verify emergency unlock procedures work correctly
  3. Confirm business applications remain functional
  4. Test integrity monitoring accuracy
  5. Validate compliance reporting completeness

This comprehensive system transforms basic file locking into an enterprise-grade protection platform with advanced security policies, compliance monitoring, and fleet management capabilities.

File Ownership Management on macOS

Master file and folder ownership operations on your Roundfleet devices using powerful command-line tools. This tutorial covers ownership changes, permission management, group assignments, and advanced ownership policies for secure file system administration.

Understanding macOS File Ownership

macOS file ownership system consists of several key concepts:

  • Owner (User) - The user who owns the file/folder and has primary control
  • Group - A collection of users who share specific permissions
  • Others - All other users on the system
  • Permissions - Read (r), Write (w), Execute (x) permissions for each category

Basic File Ownership Operations

Change File Owner

#!/bin/bash

# Change ownership of a specific file
USERNAME="Daniel"
FILE_PATH="/Users/Alex/Desktop/Dustin"

chown "$USERNAME" "$FILE_PATH"

echo "File ownership changed to $USERNAME successfully"

Change Folder Owner

#!/bin/bash

# Change ownership of a folder
USERNAME="Daniel"
FOLDER_PATH="/Users/Alex/Desktop/ProjectFolder"

chown "$USERNAME" "$FOLDER_PATH"

echo "Folder ownership changed to $USERNAME successfully"

Recursive Ownership Change

#!/bin/bash

# Change ownership recursively for all files and subfolders
USERNAME="Daniel"
FOLDER_PATH="/Users/Alex/Desktop/ProjectFolder"

chown -R "$USERNAME" "$FOLDER_PATH"

echo "Recursive ownership change completed for $USERNAME"

Advanced Ownership Management

Change Owner and Group

#!/bin/bash

# Change both owner and group
USERNAME="Daniel"
GROUPNAME="developers"
FILE_PATH="/Users/Alex/Desktop/project.txt"

chown "$USERNAME:$GROUPNAME" "$FILE_PATH"

echo "Ownership changed to $USERNAME:$GROUPNAME"

Ownership with Permission Verification

#!/bin/bash

# Change ownership and verify permissions
change_ownership_safe() {
    local username="$1"
    local file_path="$2"
    
    # Verify file exists
    if [[ ! -e "$file_path" ]]; then
        echo "Error: File or folder not found: $file_path"
        return 1
    fi
    
    # Verify user exists
    if ! id "$username" &>/dev/null; then
        echo "Error: User '$username' does not exist"
        return 1
    fi
    
    # Get current ownership
    local current_owner=$(stat -f "%Su" "$file_path")
    echo "Current owner: $current_owner"
    
    # Change ownership
    if chown "$username" "$file_path"; then
        echo "Ownership successfully changed from $current_owner to $username"
        
        # Display new permissions
        echo "New permissions:"
        ls -la "$file_path"
        return 0
    else
        echo "Error: Failed to change ownership"
        return 1
    fi
}

# Usage example
change_ownership_safe "Daniel" "/Users/Alex/Desktop/document.txt"

Bulk Ownership Management

#!/bin/bash

# Change ownership for multiple files/folders
bulk_ownership_change() {
    local username="$1"
    shift
    local paths=("$@")
    
    echo "Starting bulk ownership change to user: $username"
    
    for path in "${paths[@]}"; do
        if [[ -e "$path" ]]; then
            if chown "$username" "$path"; then
                echo "✓ Changed ownership: $path"
            else
                echo "✗ Failed to change ownership: $path"
            fi
        else
            echo "✗ File not found: $path"
        fi
    done
    
    echo "Bulk ownership change completed"
}

# Usage example
bulk_ownership_change "Daniel" "/Users/Alex/Desktop/file1.txt" "/Users/Alex/Desktop/file2.txt" "/Users/Alex/Desktop/folder1"

Permission Management

Set Specific Permissions

#!/bin/bash

# Change ownership and set specific permissions
set_ownership_and_permissions() {
    local username="$1"
    local file_path="$2"
    local permissions="$3"
    
    echo "Setting ownership and permissions for: $file_path"
    
    # Change ownership
    chown "$username" "$file_path"
    
    # Set permissions
    chmod "$permissions" "$file_path"
    
    echo "Ownership: $username, Permissions: $permissions"
    ls -la "$file_path"
}

# Usage examples
set_ownership_and_permissions "Daniel" "/Users/Alex/Desktop/script.sh" "755"
set_ownership_and_permissions "Daniel" "/Users/Alex/Desktop/document.txt" "644"

Permission Analysis

#!/bin/bash

# Analyze current permissions and ownership
analyze_permissions() {
    local file_path="$1"
    
    if [[ ! -e "$file_path" ]]; then
        echo "File or folder not found: $file_path"
        return 1
    fi
    
    echo "=== Permission Analysis for: $file_path ==="
    
    # Get detailed information
    local owner=$(stat -f "%Su" "$file_path")
    local group=$(stat -f "%Sg" "$file_path")
    local permissions=$(stat -f "%Sp" "$file_path")
    local octal_permissions=$(stat -f "%A" "$file_path")
    local size=$(stat -f "%z" "$file_path")
    local modified=$(stat -f "%Sm" "$file_path")
    
    echo "Owner: $owner"
    echo "Group: $group"
    echo "Permissions: $permissions"
    echo "Octal: $octal_permissions"
    echo "Size: $size bytes"
    echo "Modified: $modified"
    
    # Check if writable by others
    if [[ "$permissions" =~ .*w.*w.*w.* ]]; then
        echo "⚠️  WARNING: File is world-writable"
    fi
    
    # Check if executable
    if [[ "$permissions" =~ .*x.* ]]; then
        echo "ℹ️  File is executable"
    fi
}

# Usage
analyze_permissions "/Users/Alex/Desktop/document.txt"

Enterprise Ownership Management System

#!/bin/bash

# Roundfleet File Ownership Management Tool
# Comprehensive ownership and permission management for fleet devices

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_ownership.log"
REPORT_DIR="/etc/roundfleet/reports/ownership"
CONFIG_DIR="/etc/roundfleet/ownership"
POLICY_DIR="$CONFIG_DIR/policies"

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

# Ownership categories for different file types
declare -A OWNERSHIP_CATEGORIES=(
    ["system_files"]="root:wheel"
    ["application_data"]="root:admin"
    ["user_documents"]="user:staff"
    ["shared_resources"]="shared:staff"
    ["development_files"]="developer:developer"
    ["web_content"]="www:www"
    ["log_files"]="root:wheel"
    ["configuration_files"]="root:wheel"
    ["temporary_files"]="user:staff"
    ["backup_files"]="backup:backup"
)

# Ownership policies for different security levels
declare -A OWNERSHIP_POLICIES=(
    ["public_access"]="644,755,user:staff,world_readable"
    ["restricted_access"]="600,700,user:staff,owner_only"
    ["shared_collaboration"]="664,775,user:staff,group_writable"
    ["system_secure"]="644,755,root:wheel,admin_managed"
    ["development_team"]="664,775,developer:developer,team_access"
    ["confidential_data"]="600,700,secure:secure,encrypted_required"
)

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

# User and group validation
validate_user_group() {
    local user="$1"
    local group="$2"
    
    # Check if user exists
    if ! id "$user" &>/dev/null; then
        log_action "ERROR: User '$user' does not exist"
        return 1
    fi
    
    # Check if group exists (if specified)
    if [[ -n "$group" ]] && ! dscl . -read /Groups/"$group" &>/dev/null; then
        log_action "ERROR: Group '$group' does not exist"
        return 1
    fi
    
    return 0
}

# Advanced ownership change with backup and rollback
change_ownership_advanced() {
    local target_path="$1"
    local new_owner="$2"
    local new_group="${3:-}"
    local recursive="${4:-false}"
    local backup_metadata="${5:-true}"
    
    log_action "Starting advanced ownership change: $target_path -> $new_owner:$new_group"
    
    if [[ ! -e "$target_path" ]]; then
        log_action "ERROR: Target path does not exist: $target_path"
        return 1
    fi
    
    # Validate user and group
    if ! validate_user_group "$new_owner" "$new_group"; then
        return 1
    fi
    
    # Create backup of current metadata
    local backup_file=""
    if [[ "$backup_metadata" == "true" ]]; then
        backup_file="$REPORT_DIR/ownership_backup_$(date +%Y%m%d_%H%M%S).json"
        create_ownership_backup "$target_path" "$backup_file" "$recursive"
    fi
    
    # Construct chown command
    local chown_target="$new_owner"
    if [[ -n "$new_group" ]]; then
        chown_target="$new_owner:$new_group"
    fi
    
    local chown_cmd="chown"
    if [[ "$recursive" == "true" ]]; then
        chown_cmd="chown -R"
    fi
    
    # Execute ownership change
    if $chown_cmd "$chown_target" "$target_path"; then
        log_action "SUCCESS: Ownership changed to $chown_target for $target_path"
        
        # Create post-change report
        local report_file="$REPORT_DIR/ownership_change_$(date +%Y%m%d_%H%M%S).json"
        create_ownership_report "$target_path" "$report_file" "$recursive"
        
        echo "$report_file"
        return 0
    else
        log_action "ERROR: Failed to change ownership for $target_path"
        return 1
    fi
}

# Create ownership backup
create_ownership_backup() {
    local target_path="$1"
    local backup_file="$2"
    local recursive="$3"
    
    cat > "$backup_file" << EOF
{
    "backup_info": {
        "target_path": "$target_path",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "recursive": $recursive
    },
    "original_ownership": []
}
EOF
    
    if [[ "$recursive" == "true" ]]; then
        # Recursive backup
        find "$target_path" -exec stat -f '{"path":"%N","owner":"%Su","group":"%Sg","permissions":"%Sp","octal":"%A"}' {} \; | \
        jq -s '.' | \
        jq --slurpfile backup "$backup_file" '.backup_info = $backup[0].backup_info | .original_ownership = .' > "${backup_file}.tmp" && \
        mv "${backup_file}.tmp" "$backup_file"
    else
        # Single file backup
        local owner=$(stat -f "%Su" "$target_path")
        local group=$(stat -f "%Sg" "$target_path")
        local permissions=$(stat -f "%Sp" "$target_path")
        local octal=$(stat -f "%A" "$target_path")
        
        jq --arg path "$target_path" \
           --arg owner "$owner" \
           --arg group "$group" \
           --arg permissions "$permissions" \
           --arg octal "$octal" \
           '.original_ownership = [{"path": $path, "owner": $owner, "group": $group, "permissions": $permissions, "octal": $octal}]' \
           "$backup_file" > "${backup_file}.tmp" && mv "${backup_file}.tmp" "$backup_file"
    fi
    
    log_action "Ownership backup created: $backup_file"
}

# Create ownership report
create_ownership_report() {
    local target_path="$1"
    local report_file="$2"
    local recursive="$3"
    
    cat > "$report_file" << EOF
{
    "report_info": {
        "target_path": "$target_path",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "recursive": $recursive,
        "script_version": "$SCRIPT_VERSION"
    },
    "current_ownership": [],
    "security_analysis": {},
    "recommendations": []
}
EOF
    
    # Get current ownership information
    if [[ "$recursive" == "true" ]]; then
        find "$target_path" -exec stat -f '{"path":"%N","owner":"%Su","group":"%Sg","permissions":"%Sp","octal":"%A","size":%z,"modified":"%Sm"}' {} \; | \
        jq -s '.' | \
        jq --slurpfile report "$report_file" '.report_info = $report[0].report_info | .current_ownership = .' > "${report_file}.tmp" && \
        mv "${report_file}.tmp" "$report_file"
    else
        local owner=$(stat -f "%Su" "$target_path")
        local group=$(stat -f "%Sg" "$target_path")
        local permissions=$(stat -f "%Sp" "$target_path")
        local octal=$(stat -f "%A" "$target_path")
        local size=$(stat -f "%z" "$target_path")
        local modified=$(stat -f "%Sm" "$target_path")
        
        jq --arg path "$target_path" \
           --arg owner "$owner" \
           --arg group "$group" \
           --arg permissions "$permissions" \
           --arg octal "$octal" \
           --arg size "$size" \
           --arg modified "$modified" \
           '.current_ownership = [{"path": $path, "owner": $owner, "group": $group, "permissions": $permissions, "octal": $octal, "size": $size, "modified": $modified}]' \
           "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    fi
    
    # Perform security analysis
    perform_security_analysis "$target_path" "$report_file" "$recursive"
    
    log_action "Ownership report created: $report_file"
}

# Security analysis
perform_security_analysis() {
    local target_path="$1"
    local report_file="$2"
    local recursive="$3"
    
    local world_writable_count=0
    local world_readable_count=0
    local executable_count=0
    local setuid_count=0
    local security_issues=()
    
    if [[ "$recursive" == "true" ]]; then
        world_writable_count=$(find "$target_path" -type f -perm -002 2>/dev/null | wc -l)
        world_readable_count=$(find "$target_path" -type f -perm -004 2>/dev/null | wc -l)
        executable_count=$(find "$target_path" -type f -perm -111 2>/dev/null | wc -l)
        setuid_count=$(find "$target_path" -type f -perm -4000 2>/dev/null | wc -l)
    else
        local perms=$(stat -f "%A" "$target_path")
        [[ $((perms & 002)) -ne 0 ]] && world_writable_count=1
        [[ $((perms & 004)) -ne 0 ]] && world_readable_count=1
        [[ $((perms & 111)) -ne 0 ]] && executable_count=1
        [[ $((perms & 4000)) -ne 0 ]] && setuid_count=1
    fi
    
    # Identify security issues
    [[ $world_writable_count -gt 0 ]] && security_issues+=("World-writable files detected")
    [[ $setuid_count -gt 0 ]] && security_issues+=("SETUID files detected")
    
    # Update report with security analysis
    jq --argjson world_writable "$world_writable_count" \
       --argjson world_readable "$world_readable_count" \
       --argjson executable "$executable_count" \
       --argjson setuid "$setuid_count" \
       --argjson issues "$(printf '%s\n' "${security_issues[@]}" | jq -R . | jq -s .)" \
       '.security_analysis = {
           "world_writable_files": $world_writable,
           "world_readable_files": $world_readable,
           "executable_files": $executable,
           "setuid_files": $setuid,
           "security_issues": $issues
       }' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
}

# Apply ownership policy
apply_ownership_policy() {
    local target_path="$1"
    local policy_name="$2"
    local recursive="${3:-false}"
    
    log_action "Applying ownership policy '$policy_name' to $target_path"
    
    if [[ -z "${OWNERSHIP_POLICIES[$policy_name]}" ]]; then
        log_action "ERROR: Unknown ownership policy: $policy_name"
        return 1
    fi
    
    # Parse policy
    IFS=',' read -ra POLICY_PARTS <<< "${OWNERSHIP_POLICIES[$policy_name]}"
    local file_perms="${POLICY_PARTS[0]}"
    local dir_perms="${POLICY_PARTS[1]}"
    local ownership="${POLICY_PARTS[2]}"
    local access_level="${POLICY_PARTS[3]}"
    
    # Extract user and group
    IFS=':' read -ra OWNER_PARTS <<< "$ownership"
    local user="${OWNER_PARTS[0]}"
    local group="${OWNER_PARTS[1]:-}"
    
    # Apply ownership
    change_ownership_advanced "$target_path" "$user" "$group" "$recursive" "true"
    
    # Apply permissions
    if [[ -d "$target_path" ]]; then
        chmod "$dir_perms" "$target_path"
    else
        chmod "$file_perms" "$target_path"
    fi
    
    if [[ "$recursive" == "true" ]]; then
        find "$target_path" -type f -exec chmod "$file_perms" {} \;
        find "$target_path" -type d -exec chmod "$dir_perms" {} \;
    fi
    
    log_action "Policy '$policy_name' applied successfully"
}

# Fleet ownership management
manage_fleet_ownership() {
    local action="$1"
    local target_pattern="$2"
    local ownership_spec="$3"
    
    log_action "Fleet ownership management: $action on $target_pattern"
    
    case "$action" in
        "audit")
            audit_fleet_ownership "$target_pattern"
            ;;
        "standardize")
            standardize_fleet_ownership "$target_pattern" "$ownership_spec"
            ;;
        "policy-apply")
            apply_fleet_policy "$target_pattern" "$ownership_spec"
            ;;
        "report")
            generate_fleet_ownership_report
            ;;
    esac
}

# Audit fleet ownership
audit_fleet_ownership() {
    local target_pattern="$1"
    
    echo "Auditing fleet ownership for pattern: $target_pattern"
    
    # Find files matching pattern
    local files=($(find / -path "$target_pattern" 2>/dev/null | head -100))
    
    local audit_report="$REPORT_DIR/fleet_ownership_audit_$(date +%Y%m%d_%H%M%S).json"
    
    cat > "$audit_report" << EOF
{
    "audit_info": {
        "pattern": "$target_pattern",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "files_found": ${#files[@]}
    },
    "ownership_summary": {},
    "security_findings": [],
    "recommendations": []
}
EOF
    
    # Analyze ownership patterns
    local owners=()
    local groups=()
    local permissions=()
    
    for file in "${files[@]}"; do
        if [[ -e "$file" ]]; then
            owners+=($(stat -f "%Su" "$file"))
            groups+=($(stat -f "%Sg" "$file"))
            permissions+=($(stat -f "%A" "$file"))
        fi
    done
    
    # Generate summary
    local unique_owners=($(printf '%s\n' "${owners[@]}" | sort -u))
    local unique_groups=($(printf '%s\n' "${groups[@]}" | sort -u))
    
    jq --argjson owners "$(printf '%s\n' "${unique_owners[@]}" | jq -R . | jq -s .)" \
       --argjson groups "$(printf '%s\n' "${unique_groups[@]}" | jq -R . | jq -s .)" \
       '.ownership_summary = {
           "unique_owners": $owners,
           "unique_groups": $groups,
           "total_files": '${#files[@]}'
       }' "$audit_report" > "${audit_report}.tmp" && mv "${audit_report}.tmp" "$audit_report"
    
    log_action "Fleet ownership audit completed: $audit_report"
    echo "$audit_report"
}

# Main execution function
main() {
    local action="${1:-change}"
    local target="${2:-}"
    local owner="${3:-}"
    local group="${4:-}"
    local options="${5:-}"
    
    log_action "=== Roundfleet Ownership Management Started ==="
    log_action "Action: $action, Target: $target, Owner: $owner, Group: $group"
    
    case "$action" in
        "change")
            if [[ -z "$target" || -z "$owner" ]]; then
                echo "Usage: $0 change <target_path> <owner> [group] [recursive]"
                exit 1
            fi
            change_ownership_advanced "$target" "$owner" "$group" "$options"
            ;;
        "policy")
            if [[ -z "$target" || -z "$owner" ]]; then
                echo "Usage: $0 policy <target_path> <policy_name> [recursive]"
                exit 1
            fi
            apply_ownership_policy "$target" "$owner" "$group"
            ;;
        "audit")
            audit_fleet_ownership "${target:-/Users/*}"
            ;;
        "fleet")
            manage_fleet_ownership "$owner" "$target" "$group"
            ;;
        "help")
            echo "Usage: $0 [action] [options...]"
            echo "Actions:"
            echo "  change <path> <owner> [group] [recursive] - Change ownership"
            echo "  policy <path> <policy> [recursive] - Apply ownership policy"
            echo "  audit [pattern] - Audit ownership across fleet"
            echo "  fleet <action> <pattern> <spec> - Fleet management"
            echo "  help - Show this help"
            echo ""
            echo "Available policies: ${!OWNERSHIP_POLICIES[*]}"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            exit 1
            ;;
    esac
    
    log_action "=== Ownership management completed ==="
}

# Execute main function
main "$@"

Common Ownership Scenarios

Employee Role Change

#!/bin/bash

# Transfer ownership when employee changes roles
transfer_employee_files() {
    local old_user="$1"
    local new_user="$2"
    local base_path="$3"
    
    echo "Transferring files from $old_user to $new_user in $base_path"
    
    # Find all files owned by old user
    local files=($(find "$base_path" -user "$old_user" 2>/dev/null))
    
    echo "Found ${#files[@]} files owned by $old_user"
    
    for file in "${files[@]}"; do
        if chown "$new_user" "$file"; then
            echo "✓ Transferred: $file"
        else
            echo "✗ Failed: $file"
        fi
    done
    
    echo "Transfer completed"
}

# Usage
transfer_employee_files "john.doe" "jane.smith" "/Users/Shared/Projects"

Project Handover

#!/bin/bash

# Complete project handover with ownership and permissions
project_handover() {
    local project_path="$1"
    local new_owner="$2"
    local team_group="$3"
    
    echo "Starting project handover: $project_path"
    
    # Change ownership recursively
    chown -R "$new_owner:$team_group" "$project_path"
    
    # Set appropriate permissions
    find "$project_path" -type d -exec chmod 775 {} \;  # Directories
    find "$project_path" -type f -exec chmod 664 {} \;  # Files
    find "$project_path" -name "*.sh" -exec chmod 755 {} \;  # Scripts
    
    echo "Project handover completed"
    echo "New owner: $new_owner"
    echo "Team group: $team_group"
    ls -la "$project_path"
}

# Usage
project_handover "/Users/Shared/ProjectAlpha" "daniel" "developers"

Security Compliance Check

#!/bin/bash

# Check ownership compliance across critical directories
compliance_check() {
    local directories=("/etc" "/usr/local" "/Applications" "/Users/Shared")
    
    echo "=== Ownership Compliance Check ==="
    
    for dir in "${directories[@]}"; do
        if [[ -d "$dir" ]]; then
            echo -e "\nChecking: $dir"
            
            # Find world-writable files
            local world_writable=$(find "$dir" -type f -perm -002 2>/dev/null | head -5)
            if [[ -n "$world_writable" ]]; then
                echo "⚠️  World-writable files found:"
                echo "$world_writable"
            fi
            
            # Find files with unusual ownership
            local unusual_owners=$(find "$dir" -maxdepth 2 ! -user root ! -user "$(whoami)" 2>/dev/null | head -5)
            if [[ -n "$unusual_owners" ]]; then
                echo "ℹ️  Non-standard ownership:"
                echo "$unusual_owners" | xargs ls -la
            fi
        fi
    done
}

# Run compliance check
compliance_check

Important Notes

  • Admin privileges required for changing ownership of files not owned by current user
  • User validation - Always verify target user exists before changing ownership
  • Backup metadata before making bulk ownership changes
  • Test scripts on sample files before production deployment
  • Monitor permissions after ownership changes to ensure proper access
  • Use recursive options carefully to avoid unintended changes
  • Group membership affects file access even with proper ownership

File and Folder Open Management on macOS

Efficiently manage file and folder opening operations across your Roundfleet deployment with enterprise-grade security features, application control, and comprehensive audit capabilities. This tutorial transforms basic open commands into robust file access management solutions.

Understanding Enterprise File Open Operations

Enterprise file opening requires more than basic access, demanding:

  • Security validation to prevent unauthorized file access
  • Application control to enforce approved software usage
  • Permission verification before file operations
  • Audit logging for compliance tracking
  • Malware scanning integration for file safety
  • Business rules enforcement for data protection

Core Open Operations

Basic File Opening

#!/bin/bash

# Simple file open with validation
open_file() {
    local file_path="$1"
    
    # Validate file exists
    if [[ ! -f "$file_path" ]]; then
        echo "Error: File '$file_path' not found"
        return 1
    fi
    
    # Open file with default application
    if open "$file_path"; then
        echo "Successfully opened '$file_path'"
        return 0
    else
        echo "Failed to open '$file_path'"
        return 1
    fi
}

# Usage example
# open_file "/Users/admin/document.pdf"

Application-Specific File Opening

#!/bin/bash

# Open file with specific application
open_with_app() {
    local file_path="$1"
    local bundle_id="$2"
    
    # Validate file exists
    if [[ ! -f "$file_path" ]]; then
        echo "Error: File '$file_path' not found"
        return 1
    fi
    
    # Open file with specified application
    if open -b "$bundle_id" "$file_path"; then
        echo "Successfully opened '$file_path' with $bundle_id"
        return 0
    else
        echo "Failed to open '$file_path' with $bundle_id"
        return 1
    fi
}

# Usage examples
# open_with_app "/Users/admin/document.txt" "com.apple.TextEdit"
# open_with_app "/Users/admin/presentation.pptx" "com.microsoft.PowerPoint"

Folder Opening

#!/bin/bash

# Open folder in Finder
open_folder() {
    local folder_path="$1"
    
    # Validate folder exists
    if [[ ! -d "$folder_path" ]]; then
        echo "Error: Folder '$folder_path' not found"
        return 1
    fi
    
    # Open folder in Finder
    if open "$folder_path"; then
        echo "Successfully opened folder '$folder_path'"
        return 0
    else
        echo "Failed to open folder '$folder_path'"
        return 1
    fi
}

# Usage example
# open_folder "/Users/admin/Documents"

Enterprise Open Management System

#!/bin/bash

# Roundfleet Enterprise File Open Management System
# Comprehensive file and folder opening with enterprise features

# Configuration
SCRIPT_NAME="Roundfleet Open Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_open_operations.log"
QUARANTINE_DIR="/var/quarantine/roundfleet"
TEMP_DIR="/tmp/roundfleet_open"
ALLOWED_EXTENSIONS=(".pdf" ".docx" ".xlsx" ".pptx" ".txt" ".png" ".jpg" ".gif" ".mp4" ".mov" ".pages" ".numbers" ".keynote")
RESTRICTED_PATHS=("/System" "/usr/bin" "/usr/sbin" "/private/var" "/Library/LaunchDaemons" "/Library/LaunchAgents")
APPROVED_APPLICATIONS=(
    "com.apple.TextEdit"
    "com.apple.Preview"
    "com.apple.QuickTimePlayerX"
    "com.microsoft.Word"
    "com.microsoft.Excel"
    "com.microsoft.PowerPoint"
    "com.adobe.Reader"
    "com.apple.iWork.Pages"
    "com.apple.iWork.Numbers"
    "com.apple.iWork.Keynote"
)
BUSINESS_HOURS_START=9
BUSINESS_HOURS_END=17
MAX_FILE_SIZE="100M"

# Create necessary directories
mkdir -p "$TEMP_DIR"
mkdir -p "$QUARANTINE_DIR"
mkdir -p "$(dirname "$LOG_FILE")"

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

# Check if current time is within business hours
is_business_hours() {
    local current_hour=$(date +%H)
    if [[ $current_hour -ge $BUSINESS_HOURS_START && $current_hour -lt $BUSINESS_HOURS_END ]]; then
        return 0
    else
        return 1
    fi
}

# Validate file extension
is_allowed_extension() {
    local file="$1"
    local extension="${file##*.}"
    extension=".$extension"
    
    for allowed in "${ALLOWED_EXTENSIONS[@]}"; do
        if [[ "$extension" == "$allowed" ]]; then
            return 0
        fi
    done
    return 1
}

# Check if path is restricted
is_restricted_path() {
    local path="$1"
    for restricted in "${RESTRICTED_PATHS[@]}"; do
        if [[ "$path" == "$restricted"* ]]; then
            return 0
        fi
    done
    return 1
}

# Check if application is approved
is_approved_application() {
    local bundle_id="$1"
    
    for approved in "${APPROVED_APPLICATIONS[@]}"; do
        if [[ "$bundle_id" == "$approved" ]]; then
            return 0
        fi
    done
    return 1
}

# Get file size
get_file_size() {
    local file="$1"
    if [[ -f "$file" ]]; then
        stat -f%z "$file" 2>/dev/null
    else
        echo "0"
    fi
}

# Convert size string to bytes
size_to_bytes() {
    local size="$1"
    local number="${size%[A-Za-z]*}"
    local unit="${size#$number}"
    
    case "$unit" in
        "K"|"KB") echo $((number * 1024)) ;;
        "M"|"MB") echo $((number * 1024 * 1024)) ;;
        "G"|"GB") echo $((number * 1024 * 1024 * 1024)) ;;
        *) echo "$number" ;;
    esac
}

# Check file signature/magic number
check_file_signature() {
    local file="$1"
    local expected_extension="${file##*.}"
    
    if [[ ! -f "$file" ]]; then
        return 1
    fi
    
    # Get file signature
    local signature=$(file -b --mime-type "$file" 2>/dev/null)
    
    # Basic signature validation
    case "$expected_extension" in
        "pdf")
            if [[ "$signature" == "application/pdf" ]]; then
                return 0
            fi
            ;;
        "txt")
            if [[ "$signature" == "text/plain" ]]; then
                return 0
            fi
            ;;
        "docx")
            if [[ "$signature" == "application/vnd.openxmlformats-officedocument.wordprocessingml.document" ]]; then
                return 0
            fi
            ;;
        "xlsx")
            if [[ "$signature" == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ]]; then
                return 0
            fi
            ;;
        "pptx")
            if [[ "$signature" == "application/vnd.openxmlformats-officedocument.presentationml.presentation" ]]; then
                return 0
            fi
            ;;
        "png")
            if [[ "$signature" == "image/png" ]]; then
                return 0
            fi
            ;;
        "jpg"|"jpeg")
            if [[ "$signature" == "image/jpeg" ]]; then
                return 0
            fi
            ;;
        *)
            # Allow other extensions without strict validation
            return 0
            ;;
    esac
    
    log_operation "WARNING" "File signature mismatch: $file (expected: $expected_extension, detected: $signature)"
    return 1
}

# Scan file for malware (placeholder for integration)
scan_file_malware() {
    local file="$1"
    
    # Placeholder for malware scanning integration
    # This would integrate with enterprise antivirus solutions
    
    # Basic checks
    if [[ -f "$file" ]]; then
        # Check for suspicious extensions
        local extension="${file##*.}"
        case "$extension" in
            "exe"|"bat"|"cmd"|"scr"|"com"|"pif"|"vbs"|"js")
                log_operation "SECURITY" "Blocked suspicious file type: $file"
                return 1
                ;;
        esac
        
        # Check file size (extremely large files could be suspicious)
        local file_size=$(get_file_size "$file")
        if [[ $file_size -gt 1073741824 ]]; then  # 1GB
            log_operation "WARNING" "Large file detected: $file ($(format_size $file_size))"
        fi
    fi
    
    return 0
}

# Format file size
format_size() {
    local bytes="$1"
    local sizes=("B" "KB" "MB" "GB" "TB")
    local unit=0
    
    while [[ $bytes -gt 1024 && $unit -lt 4 ]]; do
        bytes=$((bytes / 1024))
        ((unit++))
    done
    
    echo "${bytes}${sizes[$unit]}"
}

# Get application info
get_app_info() {
    local bundle_id="$1"
    
    # Get application path
    local app_path=$(mdfind "kMDItemCFBundleIdentifier == '$bundle_id'" 2>/dev/null | head -1)
    
    if [[ -n "$app_path" ]]; then
        local app_name=$(basename "$app_path" .app)
        local app_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
        echo "$app_name v$app_version ($app_path)"
    else
        echo "Unknown application ($bundle_id)"
    fi
}

# Enhanced file open with enterprise features
enterprise_open_file() {
    local file_path="$1"
    local bundle_id="${2:-}"
    local force_open="${3:-false}"
    
    local operation_id=$(date +%s)
    log_operation "INFO" "Starting file open operation [$operation_id]: $file_path"
    
    # Pre-flight validations
    if [[ ! -f "$file_path" ]]; then
        log_operation "ERROR" "File not found: $file_path"
        return 1
    fi
    
    # Check if file path is restricted
    if is_restricted_path "$file_path"; then
        log_operation "SECURITY" "Blocked access to restricted path: $file_path"
        return 1
    fi
    
    # Validate file extension
    if ! is_allowed_extension "$file_path"; then
        log_operation "SECURITY" "Blocked file with unauthorized extension: $file_path"
        return 1
    fi
    
    # Check file size
    local file_size=$(get_file_size "$file_path")
    local max_size_bytes=$(size_to_bytes "$MAX_FILE_SIZE")
    
    if [[ $file_size -gt $max_size_bytes ]]; then
        log_operation "ERROR" "File too large: $(format_size $file_size) > $MAX_FILE_SIZE"
        return 1
    fi
    
    # Check file signature
    if ! check_file_signature "$file_path"; then
        if [[ "$force_open" != "true" ]]; then
            log_operation "SECURITY" "File signature validation failed: $file_path"
            return 1
        else
            log_operation "WARNING" "File signature validation failed but force_open enabled: $file_path"
        fi
    fi
    
    # Malware scanning
    if ! scan_file_malware "$file_path"; then
        log_operation "SECURITY" "File blocked by security scan: $file_path"
        return 1
    fi
    
    # Business hours check for sensitive files
    if [[ "$file_path" =~ (confidential|secret|private) ]] && ! is_business_hours; then
        log_operation "POLICY" "Sensitive file access outside business hours blocked: $file_path"
        return 1
    fi
    
    # Application validation if specified
    if [[ -n "$bundle_id" ]]; then
        if ! is_approved_application "$bundle_id"; then
            log_operation "SECURITY" "Blocked unauthorized application: $bundle_id"
            return 1
        fi
        
        # Check if application is installed
        local app_path=$(mdfind "kMDItemCFBundleIdentifier == '$bundle_id'" 2>/dev/null | head -1)
        if [[ -z "$app_path" ]]; then
            log_operation "ERROR" "Application not found: $bundle_id"
            return 1
        fi
        
        log_operation "INFO" "Opening with application: $(get_app_info "$bundle_id")"
    fi
    
    # Perform the open operation
    local open_command="open"
    if [[ -n "$bundle_id" ]]; then
        open_command="open -b '$bundle_id'"
    fi
    
    if eval "$open_command '$file_path'"; then
        log_operation "SUCCESS" "File opened successfully [$operation_id]: $file_path"
        
        # Log file access for audit
        log_operation "AUDIT" "File accessed: $file_path (size: $(format_size $file_size))"
        
        return 0
    else
        log_operation "ERROR" "Failed to open file [$operation_id]: $file_path"
        return 1
    fi
}

# Enhanced folder open with enterprise features
enterprise_open_folder() {
    local folder_path="$1"
    local reveal_hidden="${2:-false}"
    
    local operation_id=$(date +%s)
    log_operation "INFO" "Starting folder open operation [$operation_id]: $folder_path"
    
    # Pre-flight validations
    if [[ ! -d "$folder_path" ]]; then
        log_operation "ERROR" "Folder not found: $folder_path"
        return 1
    fi
    
    # Check if folder path is restricted
    if is_restricted_path "$folder_path"; then
        log_operation "SECURITY" "Blocked access to restricted folder: $folder_path"
        return 1
    fi
    
    # Business hours check for sensitive folders
    if [[ "$folder_path" =~ (confidential|secret|private) ]] && ! is_business_hours; then
        log_operation "POLICY" "Sensitive folder access outside business hours blocked: $folder_path"
        return 1
    fi
    
    # Count files in folder for audit
    local file_count=$(find "$folder_path" -type f 2>/dev/null | wc -l)
    local folder_size=$(du -sh "$folder_path" 2>/dev/null | awk '{print $1}')
    
    # Perform the open operation
    local open_command="open"
    if [[ "$reveal_hidden" == "true" ]]; then
        open_command="open -R"
    fi
    
    if eval "$open_command '$folder_path'"; then
        log_operation "SUCCESS" "Folder opened successfully [$operation_id]: $folder_path"
        log_operation "AUDIT" "Folder accessed: $folder_path (files: $file_count, size: $folder_size)"
        return 0
    else
        log_operation "ERROR" "Failed to open folder [$operation_id]: $folder_path"
        return 1
    fi
}

# Bulk file opening with progress monitoring
bulk_open_files() {
    local files_list="$1"
    local bundle_id="${2:-}"
    
    if [[ ! -f "$files_list" ]]; then
        log_operation "ERROR" "Files list not found: $files_list"
        return 1
    fi
    
    local total_files=$(grep -v '^#\|^$' "$files_list" | wc -l)
    local current_file=0
    local success_count=0
    local failure_count=0
    
    log_operation "INFO" "Starting bulk file open operation - Total files: $total_files"
    
    while IFS= read -r file_path; do
        # Skip empty lines and comments
        [[ -z "$file_path" || "$file_path" =~ ^#.* ]] && continue
        
        ((current_file++))
        
        # Trim whitespace
        file_path=$(echo "$file_path" | xargs)
        
        echo "Processing [$current_file/$total_files]: $(basename "$file_path")"
        
        if enterprise_open_file "$file_path" "$bundle_id"; then
            ((success_count++))
        else
            ((failure_count++))
        fi
        
        # Progress update
        local progress=$((current_file * 100 / total_files))
        echo "Progress: $progress% ($success_count successful, $failure_count failed)"
        
        # Small delay to prevent overwhelming the system
        sleep 0.5
        
    done < "$files_list"
    
    log_operation "SUCCESS" "Bulk open completed - Success: $success_count, Failed: $failure_count"
    return $failure_count
}

# Generate file access report
generate_access_report() {
    local report_file="/tmp/roundfleet_access_report_$(date +%Y%m%d_%H%M%S).txt"
    
    {
        echo "Roundfleet File Access Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "User: $(whoami)"
        echo "=========================="
        echo ""
        
        echo "Recent File Access Operations (Last 24 hours):"
        if [[ -f "$LOG_FILE" ]]; then
            local yesterday=$(date -v-1d '+%Y-%m-%d')
            grep "$yesterday\|$(date '+%Y-%m-%d')" "$LOG_FILE" | grep -E "(AUDIT|SUCCESS)" | tail -50
        else
            echo "No log file found"
        fi
        
        echo ""
        echo "Security Events (Last 24 hours):"
        if [[ -f "$LOG_FILE" ]]; then
            local yesterday=$(date -v-1d '+%Y-%m-%d')
            grep "$yesterday\|$(date '+%Y-%m-%d')" "$LOG_FILE" | grep -E "(SECURITY|POLICY)" | tail -20
        fi
        
        echo ""
        echo "File Access Statistics:"
        if [[ -f "$LOG_FILE" ]]; then
            echo "Total Operations: $(grep -c "file open operation\|folder open operation" "$LOG_FILE" 2>/dev/null || echo "0")"
            echo "Successful: $(grep -c "SUCCESS.*opened successfully" "$LOG_FILE" 2>/dev/null || echo "0")"
            echo "Failed: $(grep -c "ERROR.*Failed to open" "$LOG_FILE" 2>/dev/null || echo "0")"
            echo "Security Blocks: $(grep -c "SECURITY.*Blocked" "$LOG_FILE" 2>/dev/null || echo "0")"
        fi
        
        echo ""
        echo "Most Accessed File Types:"
        if [[ -f "$LOG_FILE" ]]; then
            grep "File accessed:" "$LOG_FILE" | sed 's/.*File accessed: //' | sed 's/ (size:.*//' | 
            awk -F. '{print $NF}' | sort | uniq -c | sort -nr | head -10
        fi
        
    } > "$report_file"
    
    echo "File access report saved to: $report_file"
    log_operation "INFO" "Access report generated: $report_file"
}

# Check application permissions
check_app_permissions() {
    local bundle_id="$1"
    
    # Check if application has necessary permissions
    local app_path=$(mdfind "kMDItemCFBundleIdentifier == '$bundle_id'" 2>/dev/null | head -1)
    
    if [[ -z "$app_path" ]]; then
        echo "Application not found: $bundle_id"
        return 1
    fi
    
    echo "Application: $(get_app_info "$bundle_id")"
    echo "Path: $app_path"
    
    # Check code signature
    local signature_status=$(codesign -dv "$app_path" 2>&1 | grep -E "(Signature|Authority)")
    echo "Code Signature: $signature_status"
    
    # Check if application is notarized
    local notarization=$(spctl -a -vv "$app_path" 2>&1 | grep -E "(accepted|source=)")
    echo "Notarization: $notarization"
    
    return 0
}

# Main open management function
main() {
    local action="${1:-help}"
    
    case "$action" in
        "open-file")
            local file_path="$2"
            local bundle_id="$3"
            local force_open="${4:-false}"
            
            if [[ -z "$file_path" ]]; then
                echo "Usage: $0 open-file <file_path> [bundle_id] [force_open]"
                exit 1
            fi
            
            enterprise_open_file "$file_path" "$bundle_id" "$force_open"
            ;;
        "open-folder")
            local folder_path="$2"
            local reveal_hidden="${3:-false}"
            
            if [[ -z "$folder_path" ]]; then
                echo "Usage: $0 open-folder <folder_path> [reveal_hidden]"
                exit 1
            fi
            
            enterprise_open_folder "$folder_path" "$reveal_hidden"
            ;;
        "bulk-open")
            local files_list="$2"
            local bundle_id="$3"
            
            if [[ -z "$files_list" ]]; then
                echo "Usage: $0 bulk-open <files_list> [bundle_id]"
                exit 1
            fi
            
            bulk_open_files "$files_list" "$bundle_id"
            ;;
        "check-app")
            local bundle_id="$2"
            
            if [[ -z "$bundle_id" ]]; then
                echo "Usage: $0 check-app <bundle_id>"
                exit 1
            fi
            
            check_app_permissions "$bundle_id"
            ;;
        "report")
            generate_access_report
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Enterprise File and Folder Open Management"
            echo ""
            echo "Usage: $0 <action> [options]"
            echo ""
            echo "Actions:"
            echo "  open-file <file_path> [bundle_id] [force_open]  - Open single file"
            echo "  open-folder <folder_path> [reveal_hidden]       - Open folder in Finder"
            echo "  bulk-open <files_list> [bundle_id]             - Open multiple files"
            echo "  check-app <bundle_id>                           - Check application permissions"
            echo "  report                                          - Generate access report"
            echo "  help                                            - Show this help message"
            echo ""
            echo "Common Bundle IDs:"
            echo "  com.apple.TextEdit          - TextEdit"
            echo "  com.apple.Preview           - Preview"
            echo "  com.microsoft.Word          - Microsoft Word"
            echo "  com.microsoft.Excel         - Microsoft Excel"
            echo "  com.microsoft.PowerPoint    - Microsoft PowerPoint"
            echo "  com.adobe.Reader            - Adobe Reader"
            echo "  com.apple.iWork.Pages       - Pages"
            echo "  com.apple.iWork.Numbers     - Numbers"
            echo "  com.apple.iWork.Keynote     - Keynote"
            echo ""
            echo "Features:"
            echo "  • Security validation and malware scanning"
            echo "  • Application control and approval management"
            echo "  • File signature verification"
            echo "  • Business hours compliance checking"
            echo "  • Comprehensive audit logging"
            echo "  • Bulk operations with progress monitoring"
            echo "  • Detailed access reporting"
            ;;
    esac
}

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

File and Folder Move Management on macOS

Efficiently manage file and folder move operations across your Roundfleet deployment with enterprise-grade safety features, automatic backup creation, and comprehensive audit capabilities. This tutorial transforms basic mv commands into robust data relocation solutions.

Understanding Enterprise File Move Operations

Enterprise file moving requires more than basic relocation, demanding:

  • Safety validation to prevent data loss during moves
  • Automatic backup creation before destructive operations
  • Permission preservation during relocation
  • Rollback capabilities for failed operations
  • Rename protection against naming conflicts
  • Audit logging for compliance tracking

Core Move Operations

Basic File Move

#!/bin/bash

# Simple file move with validation
move_file() {
    local source="$1"
    local destination="$2"
    
    # Validate source exists
    if [[ ! -f "$source" ]]; then
        echo "Error: Source file '$source' not found"
        return 1
    fi
    
    # Create destination directory if needed
    local dest_dir=$(dirname "$destination")
    mkdir -p "$dest_dir"
    
    # Move file
    if mv "$source" "$destination"; then
        echo "Successfully moved '$source' to '$destination'"
        return 0
    else
        echo "Failed to move '$source' to '$destination'"
        return 1
    fi
}

# Usage example
# move_file "/Users/admin/document.pdf" "/Users/shared/documents/document.pdf"

Basic Directory Move

#!/bin/bash

# Directory move with verification
move_directory() {
    local source="$1"
    local destination="$2"
    
    # Validate source directory exists
    if [[ ! -d "$source" ]]; then
        echo "Error: Source directory '$source' not found"
        return 1
    fi
    
    # Move directory
    if mv "$source" "$destination"; then
        echo "Successfully moved directory '$source' to '$destination'"
        return 0
    else
        echo "Failed to move directory '$source' to '$destination'"
        return 1
    fi
}

# Usage example
# move_directory "/Users/admin/project" "/Users/shared/projects/project"

File and Folder Rename

#!/bin/bash

# Rename file or folder
rename_item() {
    local current_path="$1"
    local new_name="$2"
    
    # Validate source exists
    if [[ ! -e "$current_path" ]]; then
        echo "Error: Source '$current_path' not found"
        return 1
    fi
    
    local parent_dir=$(dirname "$current_path")
    local new_path="$parent_dir/$new_name"
    
    # Check if new name already exists
    if [[ -e "$new_path" ]]; then
        echo "Error: '$new_path' already exists"
        return 1
    fi
    
    # Rename item
    if mv "$current_path" "$new_path"; then
        echo "Successfully renamed '$(basename "$current_path")' to '$new_name'"
        return 0
    else
        echo "Failed to rename '$(basename "$current_path")' to '$new_name'"
        return 1
    fi
}

# Usage examples
# rename_item "/Users/admin/oldfile.txt" "newfile.txt"
# rename_item "/Users/admin/old_folder" "new_folder"

Enterprise Move Management System

#!/bin/bash

# Roundfleet Enterprise File Move Management System
# Comprehensive file and folder moving with enterprise features

# Configuration
SCRIPT_NAME="Roundfleet Move Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_move_operations.log"
BACKUP_DIR="/var/backups/roundfleet/move_operations"
TEMP_DIR="/tmp/roundfleet_move"
MAX_FILE_SIZE="10G"
ALLOWED_EXTENSIONS=(".pdf" ".docx" ".xlsx" ".pptx" ".txt" ".png" ".jpg" ".gif" ".mp4" ".mov")
RESTRICTED_PATHS=("/System" "/usr/bin" "/usr/sbin" "/private/var" "/Applications")
PROTECTED_DIRECTORIES=("/Users/Shared" "/Library" "/var")
BUSINESS_HOURS_START=9
BUSINESS_HOURS_END=17

# Create necessary directories
mkdir -p "$TEMP_DIR"
mkdir -p "$BACKUP_DIR"
mkdir -p "$(dirname "$LOG_FILE")"

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

# Check if current time is within business hours
is_business_hours() {
    local current_hour=$(date +%H)
    if [[ $current_hour -ge $BUSINESS_HOURS_START && $current_hour -lt $BUSINESS_HOURS_END ]]; then
        return 0
    else
        return 1
    fi
}

# Validate file extension
is_allowed_extension() {
    local file="$1"
    local extension="${file##*.}"
    extension=".$extension"
    
    for allowed in "${ALLOWED_EXTENSIONS[@]}"; do
        if [[ "$extension" == "$allowed" ]]; then
            return 0
        fi
    done
    return 1
}

# Check if path is restricted
is_restricted_path() {
    local path="$1"
    for restricted in "${RESTRICTED_PATHS[@]}"; do
        if [[ "$path" == "$restricted"* ]]; then
            return 0
        fi
    done
    return 1
}

# Check if destination is in protected directory
is_protected_destination() {
    local path="$1"
    for protected in "${PROTECTED_DIRECTORIES[@]}"; do
        if [[ "$path" == "$protected"* ]]; then
            return 0
        fi
    done
    return 1
}

# Get file/directory size
get_item_size() {
    local item="$1"
    if [[ -f "$item" ]]; then
        stat -f%z "$item" 2>/dev/null
    elif [[ -d "$item" ]]; then
        du -sk "$item" 2>/dev/null | awk '{print $1 * 1024}'
    else
        echo "0"
    fi
}

# Convert bytes to human readable format
format_size() {
    local bytes="$1"
    local sizes=("B" "KB" "MB" "GB" "TB")
    local unit=0
    
    while [[ $bytes -gt 1024 && $unit -lt 4 ]]; do
        bytes=$((bytes / 1024))
        ((unit++))
    done
    
    echo "${bytes}${sizes[$unit]}"
}

# Calculate checksum for verification
calculate_checksum() {
    local item="$1"
    if [[ -f "$item" ]]; then
        shasum -a 256 "$item" 2>/dev/null | awk '{print $1}'
    elif [[ -d "$item" ]]; then
        find "$item" -type f -exec shasum -a 256 {} \; 2>/dev/null | shasum -a 256 | awk '{print $1}'
    else
        echo ""
    fi
}

# Create backup before move operation
create_move_backup() {
    local source="$1"
    local operation_id="$2"
    local timestamp=$(date '+%Y%m%d_%H%M%S')
    
    if [[ -e "$source" ]]; then
        local item_name=$(basename "$source")
        local backup_path="$BACKUP_DIR/${operation_id}_${item_name}_backup_$timestamp"
        
        if cp -R "$source" "$backup_path"; then
            log_operation "INFO" "Backup created: $backup_path"
            echo "$backup_path"
            return 0
        else
            log_operation "ERROR" "Failed to create backup for: $source"
            return 1
        fi
    else
        log_operation "WARNING" "Source does not exist for backup: $source"
        return 1
    fi
}

# Restore from backup
restore_from_backup() {
    local backup_path="$1"
    local restore_destination="$2"
    
    if [[ -e "$backup_path" ]]; then
        local restore_dir=$(dirname "$restore_destination")
        mkdir -p "$restore_dir"
        
        if cp -R "$backup_path" "$restore_destination"; then
            log_operation "INFO" "Restored from backup: $backup_path -> $restore_destination"
            return 0
        else
            log_operation "ERROR" "Failed to restore from backup: $backup_path"
            return 1
        fi
    else
        log_operation "ERROR" "Backup not found: $backup_path"
        return 1
    fi
}

# Check for naming conflicts
check_naming_conflict() {
    local destination="$1"
    local resolve_method="${2:-prompt}"  # prompt, overwrite, rename, skip
    
    if [[ -e "$destination" ]]; then
        case "$resolve_method" in
            "overwrite")
                log_operation "WARNING" "Will overwrite existing item: $destination"
                return 0
                ;;
            "rename")
                local counter=1
                local base_name="${destination%.*}"
                local extension="${destination##*.}"
                local new_destination
                
                while true; do
                    if [[ "$base_name" == "$destination" ]]; then
                        # No extension
                        new_destination="${destination}_${counter}"
                    else
                        new_destination="${base_name}_${counter}.${extension}"
                    fi
                    
                    if [[ ! -e "$new_destination" ]]; then
                        echo "$new_destination"
                        log_operation "INFO" "Resolved naming conflict: $destination -> $new_destination"
                        return 0
                    fi
                    ((counter++))
                done
                ;;
            "skip")
                log_operation "INFO" "Skipping due to naming conflict: $destination"
                return 2
                ;;
            "prompt"|*)
                log_operation "ERROR" "Naming conflict detected: $destination"
                return 1
                ;;
        esac
    else
        echo "$destination"
        return 0
    fi
}

# Verify move operation integrity
verify_move_integrity() {
    local source_backup="$1"
    local destination="$2"
    
    if [[ -e "$source_backup" && -e "$destination" ]]; then
        local backup_checksum=$(calculate_checksum "$source_backup")
        local dest_checksum=$(calculate_checksum "$destination")
        
        if [[ "$backup_checksum" == "$dest_checksum" ]]; then
            log_operation "INFO" "Move integrity verification passed: $destination"
            return 0
        else
            log_operation "ERROR" "Move integrity verification failed: $destination"
            return 1
        fi
    else
        log_operation "WARNING" "Cannot verify move integrity - missing backup or destination"
        return 1
    fi
}

# Enhanced file move with enterprise features
enterprise_move_file() {
    local source="$1"
    local destination="$2"
    local conflict_resolution="${3:-prompt}"  # prompt, overwrite, rename, skip
    local create_backup="${4:-true}"
    local verify_integrity="${5:-true}"
    
    local operation_id=$(date +%s)
    log_operation "INFO" "Starting file move operation [$operation_id]: $source -> $destination"
    
    # Pre-flight validations
    if [[ ! -f "$source" ]]; then
        log_operation "ERROR" "Source file not found: $source"
        return 1
    fi
    
    # Check if source is restricted
    if is_restricted_path "$source"; then
        log_operation "ERROR" "Source path is restricted: $source"
        return 1
    fi
    
    # Check if destination is restricted
    if is_restricted_path "$destination"; then
        log_operation "ERROR" "Destination path is restricted: $destination"
        return 1
    fi
    
    # Validate file extension
    if ! is_allowed_extension "$source"; then
        log_operation "WARNING" "File extension not in allowed list: $source"
    fi
    
    # Check file size
    local file_size=$(get_item_size "$source")
    local max_size_bytes=$(echo "$MAX_FILE_SIZE" | sed 's/G//' | awk '{print $1 * 1024 * 1024 * 1024}')
    
    if [[ $file_size -gt $max_size_bytes ]]; then
        log_operation "ERROR" "File too large: $(format_size $file_size) > $MAX_FILE_SIZE"
        return 1
    fi
    
    # Business hours check for large files (>100MB)
    if [[ $file_size -gt 104857600 ]] && ! is_business_hours; then
        log_operation "WARNING" "Large file move outside business hours: $(format_size $file_size)"
    fi
    
    # Check for naming conflicts
    local resolved_destination
    resolved_destination=$(check_naming_conflict "$destination" "$conflict_resolution")
    local conflict_result=$?
    
    if [[ $conflict_result -eq 1 ]]; then
        log_operation "ERROR" "Naming conflict resolution failed: $destination"
        return 1
    elif [[ $conflict_result -eq 2 ]]; then
        log_operation "INFO" "Move operation skipped due to conflict: $destination"
        return 0
    fi
    
    destination="$resolved_destination"
    
    # Create destination directory
    local dest_dir=$(dirname "$destination")
    if ! mkdir -p "$dest_dir"; then
        log_operation "ERROR" "Failed to create destination directory: $dest_dir"
        return 1
    fi
    
    # Create backup if requested
    local backup_path=""
    if [[ "$create_backup" == "true" ]]; then
        backup_path=$(create_move_backup "$source" "$operation_id")
        if [[ $? -ne 0 ]]; then
            log_operation "ERROR" "Failed to create backup for: $source"
            return 1
        fi
    fi
    
    # Perform the move operation
    if mv "$source" "$destination"; then
        log_operation "INFO" "File moved successfully: $(format_size $file_size)"
        
        # Verify integrity if requested and backup exists
        if [[ "$verify_integrity" == "true" && -n "$backup_path" ]]; then
            if ! verify_move_integrity "$backup_path" "$destination"; then
                log_operation "ERROR" "Move integrity verification failed, attempting restore"
                
                # Restore from backup
                if [[ -n "$backup_path" ]]; then
                    restore_from_backup "$backup_path" "$source"
                    rm -f "$destination"
                fi
                return 1
            fi
        fi
        
        # Log successful operation
        log_operation "SUCCESS" "File move completed [$operation_id]: $source -> $destination"
        return 0
    else
        log_operation "ERROR" "Move operation failed [$operation_id]: $source -> $destination"
        return 1
    fi
}

# Enhanced directory move with enterprise features
enterprise_move_directory() {
    local source="$1"
    local destination="$2"
    local conflict_resolution="${3:-prompt}"
    local create_backup="${4:-true}"
    local verify_integrity="${5:-true}"
    
    local operation_id=$(date +%s)
    log_operation "INFO" "Starting directory move operation [$operation_id]: $source -> $destination"
    
    # Pre-flight validations
    if [[ ! -d "$source" ]]; then
        log_operation "ERROR" "Source directory not found: $source"
        return 1
    fi
    
    # Check if source is restricted
    if is_restricted_path "$source"; then
        log_operation "ERROR" "Source path is restricted: $source"
        return 1
    fi
    
    # Check if destination is restricted
    if is_restricted_path "$destination"; then
        log_operation "ERROR" "Destination path is restricted: $destination"
        return 1
    fi
    
    # Calculate directory size and file count
    local dir_size=$(get_item_size "$source")
    local file_count=$(find "$source" -type f | wc -l)
    
    log_operation "INFO" "Directory stats - Size: $(format_size $dir_size), Files: $file_count"
    
    # Business hours check for large directories (>1GB or >1000 files)
    if [[ $dir_size -gt 1073741824 || $file_count -gt 1000 ]] && ! is_business_hours; then
        log_operation "WARNING" "Large directory move outside business hours"
    fi
    
    # Check for naming conflicts
    local resolved_destination
    resolved_destination=$(check_naming_conflict "$destination" "$conflict_resolution")
    local conflict_result=$?
    
    if [[ $conflict_result -eq 1 ]]; then
        log_operation "ERROR" "Naming conflict resolution failed: $destination"
        return 1
    elif [[ $conflict_result -eq 2 ]]; then
        log_operation "INFO" "Move operation skipped due to conflict: $destination"
        return 0
    fi
    
    destination="$resolved_destination"
    
    # Create parent directory for destination
    local dest_parent=$(dirname "$destination")
    if ! mkdir -p "$dest_parent"; then
        log_operation "ERROR" "Failed to create destination parent directory: $dest_parent"
        return 1
    fi
    
    # Create backup if requested
    local backup_path=""
    if [[ "$create_backup" == "true" ]]; then
        backup_path=$(create_move_backup "$source" "$operation_id")
        if [[ $? -ne 0 ]]; then
            log_operation "ERROR" "Failed to create backup for: $source"
            return 1
        fi
    fi
    
    # Perform the move operation
    if mv "$source" "$destination"; then
        log_operation "INFO" "Directory moved successfully: $(format_size $dir_size)"
        
        # Verify integrity if requested and backup exists
        if [[ "$verify_integrity" == "true" && -n "$backup_path" ]]; then
            if ! verify_move_integrity "$backup_path" "$destination"; then
                log_operation "ERROR" "Directory move integrity verification failed, attempting restore"
                
                # Restore from backup
                if [[ -n "$backup_path" ]]; then
                    restore_from_backup "$backup_path" "$source"
                    rm -rf "$destination"
                fi
                return 1
            fi
        fi
        
        # Log successful operation
        log_operation "SUCCESS" "Directory move completed [$operation_id]: $source -> $destination"
        return 0
    else
        log_operation "ERROR" "Directory move operation failed [$operation_id]: $source -> $destination"
        return 1
    fi
}

# Enhanced rename with enterprise features
enterprise_rename() {
    local current_path="$1"
    local new_name="$2"
    local create_backup="${3:-true}"
    
    local operation_id=$(date +%s)
    log_operation "INFO" "Starting rename operation [$operation_id]: $(basename "$current_path") -> $new_name"
    
    # Validate source exists
    if [[ ! -e "$current_path" ]]; then
        log_operation "ERROR" "Source not found: $current_path"
        return 1
    fi
    
    # Check if source is restricted
    if is_restricted_path "$current_path"; then
        log_operation "ERROR" "Source path is restricted: $current_path"
        return 1
    fi
    
    local parent_dir=$(dirname "$current_path")
    local new_path="$parent_dir/$new_name"
    
    # Check if new name already exists
    if [[ -e "$new_path" ]]; then
        log_operation "ERROR" "Target name already exists: $new_path"
        return 1
    fi
    
    # Validate new name (no special characters that could cause issues)
    if [[ "$new_name" =~ [/\\:*?"<>|] ]]; then
        log_operation "ERROR" "Invalid characters in new name: $new_name"
        return 1
    fi
    
    # Create backup if requested
    local backup_path=""
    if [[ "$create_backup" == "true" ]]; then
        backup_path=$(create_move_backup "$current_path" "$operation_id")
        if [[ $? -ne 0 ]]; then
            log_operation "WARNING" "Failed to create backup for rename operation"
        fi
    fi
    
    # Perform rename
    if mv "$current_path" "$new_path"; then
        log_operation "SUCCESS" "Rename completed [$operation_id]: $(basename "$current_path") -> $new_name"
        return 0
    else
        log_operation "ERROR" "Rename operation failed [$operation_id]: $(basename "$current_path") -> $new_name"
        return 1
    fi
}

# Bulk move operations with progress monitoring
bulk_move_operation() {
    local operation_type="$1"  # "file", "directory", or "rename"
    local operations_file="$2" # File containing operation definitions
    local conflict_resolution="${3:-rename}"
    
    if [[ ! -f "$operations_file" ]]; then
        log_operation "ERROR" "Operations file not found: $operations_file"
        return 1
    fi
    
    local total_operations=$(grep -v '^#\|^$' "$operations_file" | wc -l)
    local current_operation=0
    local success_count=0
    local failure_count=0
    
    log_operation "INFO" "Starting bulk move operation - Total operations: $total_operations"
    
    while IFS='|' read -r source destination; do
        # Skip empty lines and comments
        [[ -z "$source" || "$source" =~ ^#.* ]] && continue
        
        ((current_operation++))
        
        # Trim whitespace
        source=$(echo "$source" | xargs)
        destination=$(echo "$destination" | xargs)
        
        echo "Processing [$current_operation/$total_operations]: $(basename "$source")"
        
        case "$operation_type" in
            "file")
                if enterprise_move_file "$source" "$destination" "$conflict_resolution"; then
                    ((success_count++))
                else
                    ((failure_count++))
                fi
                ;;
            "directory")
                if enterprise_move_directory "$source" "$destination" "$conflict_resolution"; then
                    ((success_count++))
                else
                    ((failure_count++))
                fi
                ;;
            "rename")
                if enterprise_rename "$source" "$destination"; then
                    ((success_count++))
                else
                    ((failure_count++))
                fi
                ;;
        esac
        
        # Progress update
        local progress=$((current_operation * 100 / total_operations))
        echo "Progress: $progress% ($success_count successful, $failure_count failed)"
        
    done < "$operations_file"
    
    log_operation "SUCCESS" "Bulk move completed - Success: $success_count, Failed: $failure_count"
    return $failure_count
}

# Generate move operations report
generate_move_report() {
    local report_file="/tmp/roundfleet_move_report_$(date +%Y%m%d_%H%M%S).txt"
    
    {
        echo "Roundfleet Move Operations Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "=============================="
        echo ""
        
        echo "Recent Move Operations (Last 24 hours):"
        if [[ -f "$LOG_FILE" ]]; then
            local yesterday=$(date -v-1d '+%Y-%m-%d')
            grep "$yesterday\|$(date '+%Y-%m-%d')" "$LOG_FILE" | tail -50
        else
            echo "No log file found"
        fi
        
        echo ""
        echo "System Information:"
        echo "Available Space:"
        df -h | grep -E "^/dev/"
        
        echo ""
        echo "Backup Directory Status:"
        if [[ -d "$BACKUP_DIR" ]]; then
            echo "Backup Location: $BACKUP_DIR"
            echo "Backup Count: $(find "$BACKUP_DIR" -type f | wc -l)"
            echo "Backup Size: $(du -sh "$BACKUP_DIR" 2>/dev/null | awk '{print $1}')"
        else
            echo "Backup directory not found"
        fi
        
        echo ""
        echo "Move Operation Statistics:"
        if [[ -f "$LOG_FILE" ]]; then
            echo "Total Operations: $(grep -c "move operation\|rename operation" "$LOG_FILE" 2>/dev/null || echo "0")"
            echo "Successful: $(grep -c "SUCCESS.*completed" "$LOG_FILE" 2>/dev/null || echo "0")"
            echo "Failed: $(grep -c "ERROR.*failed" "$LOG_FILE" 2>/dev/null || echo "0")"
        fi
        
    } > "$report_file"
    
    echo "Move operations report saved to: $report_file"
    log_operation "INFO" "Move report generated: $report_file"
}

# Cleanup old backups
cleanup_old_backups() {
    local retention_days="${1:-30}"
    
    log_operation "INFO" "Starting backup cleanup - Retention: $retention_days days"
    
    if [[ -d "$BACKUP_DIR" ]]; then
        local deleted_count=0
        
        # Find and delete backups older than retention period
        while IFS= read -r -d '' backup_file; do
            if rm -rf "$backup_file"; then
                ((deleted_count++))
                log_operation "INFO" "Deleted old backup: $(basename "$backup_file")"
            fi
        done < <(find "$BACKUP_DIR" -type f -mtime +$retention_days -print0 2>/dev/null)
        
        log_operation "SUCCESS" "Backup cleanup completed - Deleted: $deleted_count items"
    else
        log_operation "WARNING" "Backup directory not found: $BACKUP_DIR"
    fi
}

# Main move management function
main() {
    local action="${1:-help}"
    
    case "$action" in
        "move-file")
            local source="$2"
            local destination="$3"
            local conflict_resolution="${4:-prompt}"
            local create_backup="${5:-true}"
            local verify="${6:-true}"
            
            if [[ -z "$source" || -z "$destination" ]]; then
                echo "Usage: $0 move-file <source> <destination> [conflict_resolution] [create_backup] [verify_integrity]"
                exit 1
            fi
            
            enterprise_move_file "$source" "$destination" "$conflict_resolution" "$create_backup" "$verify"
            ;;
        "move-directory")
            local source="$2"
            local destination="$3"
            local conflict_resolution="${4:-prompt}"
            local create_backup="${5:-true}"
            local verify="${6:-true}"
            
            if [[ -z "$source" || -z "$destination" ]]; then
                echo "Usage: $0 move-directory <source> <destination> [conflict_resolution] [create_backup] [verify_integrity]"
                exit 1
            fi
            
            enterprise_move_directory "$source" "$destination" "$conflict_resolution" "$create_backup" "$verify"
            ;;
        "rename")
            local current_path="$2"
            local new_name="$3"
            local create_backup="${4:-true}"
            
            if [[ -z "$current_path" || -z "$new_name" ]]; then
                echo "Usage: $0 rename <current_path> <new_name> [create_backup]"
                exit 1
            fi
            
            enterprise_rename "$current_path" "$new_name" "$create_backup"
            ;;
        "bulk-files")
            local operations_file="$2"
            local conflict_resolution="${3:-rename}"
            
            if [[ -z "$operations_file" ]]; then
                echo "Usage: $0 bulk-files <operations_file> [conflict_resolution]"
                exit 1
            fi
            
            bulk_move_operation "file" "$operations_file" "$conflict_resolution"
            ;;
        "bulk-directories")
            local operations_file="$2"
            local conflict_resolution="${3:-rename}"
            
            if [[ -z "$operations_file" ]]; then
                echo "Usage: $0 bulk-directories <operations_file> [conflict_resolution]"
                exit 1
            fi
            
            bulk_move_operation "directory" "$operations_file" "$conflict_resolution"
            ;;
        "bulk-rename")
            local operations_file="$2"
            
            if [[ -z "$operations_file" ]]; then
                echo "Usage: $0 bulk-rename <operations_file>"
                exit 1
            fi
            
            bulk_move_operation "rename" "$operations_file"
            ;;
        "report")
            generate_move_report
            ;;
        "cleanup-backups")
            local retention_days="${2:-30}"
            cleanup_old_backups "$retention_days"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Enterprise File and Folder Move Management"
            echo ""
            echo "Usage: $0 <action> [options]"
            echo ""
            echo "Actions:"
            echo "  move-file <source> <destination>           - Move single file"
            echo "  move-directory <source> <destination>      - Move directory"
            echo "  rename <current_path> <new_name>           - Rename file or folder"
            echo "  bulk-files <operations_file>               - Bulk move files"
            echo "  bulk-directories <operations_file>         - Bulk move directories"
            echo "  bulk-rename <operations_file>              - Bulk rename operations"
            echo "  report                                      - Generate operations report"
            echo "  cleanup-backups [retention_days]           - Clean old backups (default: 30 days)"
            echo "  help                                        - Show this help message"
            echo ""
            echo "Conflict Resolution Options:"
            echo "  prompt     - Stop and prompt for resolution (default)"
            echo "  overwrite  - Overwrite existing items"
            echo "  rename     - Auto-rename with counter suffix"
            echo "  skip       - Skip conflicting operations"
            echo ""
            echo "Operations File Format (source|destination per line):"
            echo "  /path/to/source1.txt|/path/to/destination1.txt"
            echo "  /path/to/source2.pdf|/path/to/destination2.pdf"
            echo ""
            echo "Features:"
            echo "  • Safety validation and automatic backup creation"
            echo "  • Conflict resolution with multiple strategies"
            echo "  • Business hours compliance checking"
            echo "  • Comprehensive audit logging"
            echo "  • Integrity verification"
            echo "  • Bulk operations with progress monitoring"
            echo "  • Automatic backup cleanup"
            ;;
    esac
}

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

Quick Reference Commands

Single File Operations

# Move file with full enterprise features
./move_manager.sh move-file "/Users/admin/document.pdf" "/Users/shared/documents/document.pdf"

# Move file with overwrite conflict resolution
./move_manager.sh move-file "/source/file.txt" "/destination/file.txt" overwrite

# Move file with auto-rename on conflicts
./move_manager.sh move-file "/source/file.txt" "/destination/file.txt" rename

# Move file without backup creation
./move_manager.sh move-file "/source/file.txt" "/destination/file.txt" prompt false

Directory Operations

# Move directory with all contents
./move_manager.sh move-directory "/Users/admin/project" "/Users/shared/projects/project"

# Move directory with rename on conflicts
./move_manager.sh move-directory "/source/folder" "/destination/folder" rename

Rename Operations

# Rename file
./move_manager.sh rename "/Users/admin/oldfile.txt" "newfile.txt"

# Rename directory
./move_manager.sh rename "/Users/admin/old_folder" "new_folder"

# Rename without backup
./move_manager.sh rename "/path/to/item" "new_name" false

Bulk Operations

# Create operations file for bulk moves
cat > /tmp/move_operations.txt << EOF
/Users/admin/doc1.pdf|/Users/shared/documents/doc1.pdf
/Users/admin/doc2.pdf|/Users/shared/documents/doc2.pdf
/Users/admin/doc3.pdf|/Users/shared/documents/doc3.pdf
EOF

# Execute bulk file moves
./move_manager.sh bulk-files "/tmp/move_operations.txt" rename

# Create rename operations file
cat > /tmp/rename_operations.txt << EOF
/Users/admin/oldname1.txt|newname1.txt
/Users/admin/oldname2.pdf|newname2.pdf
EOF

# Execute bulk renames
./move_manager.sh bulk-rename "/tmp/rename_operations.txt"

Integration Examples

JAMF Pro Integration

#!/bin/bash

# JAMF Pro script for enterprise file moves
# Parameters: $4 = operation_type, $5 = source_path, $6 = destination_path, $7 = conflict_resolution

OPERATION_TYPE="$4"
SOURCE_PATH="$5"
DESTINATION_PATH="$6"
CONFLICT_RESOLUTION="${7:-rename}"

# Download move manager if not present
if [[ ! -f "/usr/local/bin/roundfleet_move_manager.sh" ]]; then
    curl -o "/usr/local/bin/roundfleet_move_manager.sh" "https://scripts.roundfleet.com/move_manager.sh"
    chmod +x "/usr/local/bin/roundfleet_move_manager.sh"
fi

# Execute move operation
case "$OPERATION_TYPE" in
    "file")
        /usr/local/bin/roundfleet_move_manager.sh move-file "$SOURCE_PATH" "$DESTINATION_PATH" "$CONFLICT_RESOLUTION"
        ;;
    "directory")
        /usr/local/bin/roundfleet_move_manager.sh move-directory "$SOURCE_PATH" "$DESTINATION_PATH" "$CONFLICT_RESOLUTION"
        ;;
    "rename")
        /usr/local/bin/roundfleet_move_manager.sh rename "$SOURCE_PATH" "$DESTINATION_PATH"
        ;;
    *)
        echo "Invalid operation type: $OPERATION_TYPE"
        exit 1
        ;;
esac

# Generate report
/usr/local/bin/roundfleet_move_manager.sh report

exit $?

Configuration Profile for Move Policies

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>PayloadContent</key>
    <array>
        <dict>
            <key>PayloadType</key>
            <string>com.roundfleet.move.policy</string>
            <key>PayloadIdentifier</key>
            <string>com.roundfleet.move.policy.main</string>
            <key>PayloadDisplayName</key>
            <string>Roundfleet Move Policy</string>
            <key>MaxFileSize</key>
            <string>10G</string>
            <key>AllowedExtensions</key>
            <array>
                <string>.pdf</string>
                <string>.docx</string>
                <string>.xlsx</string>
                <string>.pptx</string>
            </array>
            <key>ConflictResolution</key>
            <string>rename</string>
            <key>BusinessHoursOnly</key>
            <true/>
            <key>CreateBackups</key>
            <true/>
            <key>BackupRetentionDays</key>
            <integer>30</integer>
        </dict>
    </array>
</dict>
</plist>

Security and Compliance Features

Automated Backup Management

# Schedule daily backup cleanup
cat > /etc/cron.daily/roundfleet-move-cleanup << 'EOF'
#!/bin/bash
/usr/local/bin/roundfleet_move_manager.sh cleanup-backups 30
EOF

chmod +x /etc/cron.daily/roundfleet-move-cleanup

Compliance Reporting

# Generate compliance report for auditors
generate_compliance_report() {
    local report_file="/var/reports/move_compliance_$(date +%Y%m%d).csv"
    
    echo "Timestamp,Operation_ID,User,Source,Destination,Size,Status,Backup_Path" > "$report_file"
    
    # Parse log file for move operations
    grep "move operation\|rename operation" "$LOG_FILE" | while read line; do
        # Extract relevant information and format as CSV
        echo "$line" | awk -F' - ' '{print $1","$2}' >> "$report_file"
    done
    
    echo "Compliance report generated: $report_file"
}

Troubleshooting

Common Issues and Solutions

IssueCauseSolution
Permission deniedInsufficient privilegesRun with sudo or check file permissions
Cross-device linkMoving across filesystemsUse copy + delete instead of mv
File in useApplication has file openClose application or use force option
Naming conflictDestination existsUse conflict resolution strategy
Operation timeoutLarge directory/slow diskBreak into smaller operations

Recovery Procedures

# List available backups
ls -la /var/backups/roundfleet/move_operations/

# Restore from specific backup
./move_manager.sh restore-backup "/var/backups/roundfleet/move_operations/backup_file" "/restore/destination"

# Check move operation logs
tail -f /var/log/roundfleet_move_operations.log

# Search for failed operations
grep "ERROR" /var/log/roundfleet_move_operations.log

Best Practices

  1. Always test on single device before fleet deployment
  2. Use backup creation for critical operations
  3. Monitor disk space before large move operations
  4. Choose appropriate conflict resolution for your use case
  5. Regular backup cleanup to manage disk usage
  6. Review logs regularly for failed operations
  7. Use business hours restrictions for resource-intensive moves
  8. Implement proper file naming conventions to avoid conflicts

This enterprise move management system provides comprehensive safety, backup, and recovery features while maintaining the simplicity and efficiency of basic move operations for effective fleet management.

File and Folder Permissions Management on macOS

Manage file and folder permissions across your Roundfleet devices using command-line tools. This tutorial covers permission models, ownership management, access control implementation, and enterprise-wide permission policy deployment.

Understanding macOS Permission System

macOS uses a Unix-based permission system with three types of permissions and three user categories:

Permission Types

  • Read (r) - View file contents or list directory contents
  • Write (w) - Modify file contents or create/delete files in directory
  • Execute (x) - Run file as program or access directory

User Categories

  • Owner (u) - The user who created the file/folder
  • Group (g) - Users belonging to the file's group
  • Others (o) - All other system users

Permission Representations

ReadWriteExecuteOctalSymbolic
✗✗✗0---
✗✗✓1--x
✗✓✗2-w-
✗✓✓3-wx
✓✗✗4r--
✓✗✓5r-x
✓✓✗6rw-
✓✓✓7rwx

Basic Permission Management

View File/Folder Permissions

#!/bin/bash

# View permissions for specific file or folder
TARGET_PATH="$1"

if [[ -z "$TARGET_PATH" ]]; then
    echo "❌ Please specify a file or folder path"
    echo "Usage: $0 /path/to/file/or/folder"
    exit 1
fi

if [[ ! -e "$TARGET_PATH" ]]; then
    echo "❌ Path does not exist: $TARGET_PATH"
    exit 1
fi

echo "📋 Permission details for: $TARGET_PATH"
ls -la "$TARGET_PATH"

echo ""
echo "📊 Detailed permission breakdown:"
ls -la "$TARGET_PATH" | while read -r line; do
    if [[ "$line" != total* ]]; then
        echo "Full output: $line"
        
        # Extract permission string
        perms=$(echo "$line" | awk '{print $1}')
        if [[ ${#perms} -eq 10 ]]; then
            echo "File type: ${perms:0:1}"
            echo "Owner permissions: ${perms:1:3}"
            echo "Group permissions: ${perms:4:3}"
            echo "Others permissions: ${perms:7:3}"
        fi
    fi
done

Set Permissions Using Octal Notation

#!/bin/bash

# Set permissions using octal notation (e.g., 755, 644)
TARGET_PATH="$1"
PERMISSION="$2"

if [[ -z "$TARGET_PATH" || -z "$PERMISSION" ]]; then
    echo "❌ Please specify path and permission"
    echo "Usage: $0 /path/to/file 755"
    echo "Common permissions:"
    echo "  755 - rwxr-xr-x (owner: full, group/others: read+execute)"
    echo "  644 - rw-r--r-- (owner: read+write, group/others: read-only)"
    echo "  600 - rw------- (owner: read+write, group/others: no access)"
    exit 1
fi

if [[ ! -e "$TARGET_PATH" ]]; then
    echo "❌ Path does not exist: $TARGET_PATH"
    exit 1
fi

# Validate permission format
if [[ ! "$PERMISSION" =~ ^[0-7]{3}$ ]]; then
    echo "❌ Invalid permission format. Use 3-digit octal (e.g., 755)"
    exit 1
fi

echo "🔧 Setting permissions $PERMISSION on: $TARGET_PATH"

# Show current permissions
echo "Current permissions:"
ls -la "$TARGET_PATH"

# Apply new permissions
if chmod "$PERMISSION" "$TARGET_PATH"; then
    echo "✅ Permissions updated successfully"
    
    echo "New permissions:"
    ls -la "$TARGET_PATH"
else
    echo "❌ Failed to set permissions"
    exit 1
fi

Set Permissions Using Symbolic Notation

#!/bin/bash

# Set permissions using symbolic notation (e.g., u=rwx,g=rx,o=r)
TARGET_PATH="$1"
PERMISSION="$2"

if [[ -z "$TARGET_PATH" || -z "$PERMISSION" ]]; then
    echo "❌ Please specify path and permission"
    echo "Usage: $0 /path/to/file 'u=rwx,g=rx,o=r'"
    echo "Symbolic notation examples:"
    echo "  u=rwx,g=rx,o=rx  - Owner: full, Group/Others: read+execute"
    echo "  u=rw,g=r,o=r     - Owner: read+write, Group/Others: read-only"
    echo "  u=rw,g=,o=       - Owner: read+write, Group/Others: no access"
    exit 1
fi

if [[ ! -e "$TARGET_PATH" ]]; then
    echo "❌ Path does not exist: $TARGET_PATH"
    exit 1
fi

echo "🔧 Setting permissions '$PERMISSION' on: $TARGET_PATH"

# Show current permissions
echo "Current permissions:"
ls -la "$TARGET_PATH"

# Apply new permissions
if chmod "$PERMISSION" "$TARGET_PATH"; then
    echo "✅ Permissions updated successfully"
    
    echo "New permissions:"
    ls -la "$TARGET_PATH"
else
    echo "❌ Failed to set permissions"
    exit 1
fi

Ownership Management

Change File/Folder Owner

#!/bin/bash

# Change ownership of file or folder
TARGET_PATH="$1"
NEW_OWNER="$2"

if [[ -z "$TARGET_PATH" || -z "$NEW_OWNER" ]]; then
    echo "❌ Please specify path and new owner"
    echo "Usage: $0 /path/to/file username"
    exit 1
fi

if [[ ! -e "$TARGET_PATH" ]]; then
    echo "❌ Path does not exist: $TARGET_PATH"
    exit 1
fi

# Verify user exists
if ! id "$NEW_OWNER" &>/dev/null; then
    echo "❌ User does not exist: $NEW_OWNER"
    echo "Available users:"
    dscl . list /Users | grep -v "^_"
    exit 1
fi

echo "👤 Changing owner of '$TARGET_PATH' to: $NEW_OWNER"

# Show current ownership
echo "Current ownership:"
ls -la "$TARGET_PATH"

# Change ownership
if sudo chown "$NEW_OWNER" "$TARGET_PATH"; then
    echo "✅ Ownership changed successfully"
    
    echo "New ownership:"
    ls -la "$TARGET_PATH"
else
    echo "❌ Failed to change ownership"
    exit 1
fi

Change File/Folder Group

#!/bin/bash

# Change group ownership of file or folder
TARGET_PATH="$1"
NEW_GROUP="$2"

if [[ -z "$TARGET_PATH" || -z "$NEW_GROUP" ]]; then
    echo "❌ Please specify path and new group"
    echo "Usage: $0 /path/to/file groupname"
    echo "Common groups: admin, staff, wheel, everyone"
    exit 1
fi

if [[ ! -e "$TARGET_PATH" ]]; then
    echo "❌ Path does not exist: $TARGET_PATH"
    exit 1
fi

# Verify group exists
if ! dscl . read /Groups/"$NEW_GROUP" &>/dev/null; then
    echo "❌ Group does not exist: $NEW_GROUP"
    echo "Available groups:"
    dscl . list /Groups | grep -v "^_"
    exit 1
fi

echo "👥 Changing group of '$TARGET_PATH' to: $NEW_GROUP"

# Show current ownership
echo "Current ownership:"
ls -la "$TARGET_PATH"

# Change group ownership
if sudo chgrp "$NEW_GROUP" "$TARGET_PATH"; then
    echo "✅ Group ownership changed successfully"
    
    echo "New ownership:"
    ls -la "$TARGET_PATH"
else
    echo "❌ Failed to change group ownership"
    exit 1
fi

Recursive Permission Management

Set Permissions Recursively

#!/bin/bash

# Set permissions recursively on directory and all contents
TARGET_DIR="$1"
DIR_PERMISSION="$2"
FILE_PERMISSION="$3"

if [[ -z "$TARGET_DIR" || -z "$DIR_PERMISSION" || -z "$FILE_PERMISSION" ]]; then
    echo "❌ Please specify directory path and permissions"
    echo "Usage: $0 /path/to/directory 755 644"
    echo "This will set directories to 755 and files to 644"
    exit 1
fi

if [[ ! -d "$TARGET_DIR" ]]; then
    echo "❌ Directory does not exist: $TARGET_DIR"
    exit 1
fi

echo "🔄 Setting recursive permissions on: $TARGET_DIR"
echo "Directories will be set to: $DIR_PERMISSION"
echo "Files will be set to: $FILE_PERMISSION"

# Count items to process
dir_count=$(find "$TARGET_DIR" -type d | wc -l)
file_count=$(find "$TARGET_DIR" -type f | wc -l)

echo "Found $dir_count directories and $file_count files to process"

read -p "Continue? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    echo "Operation cancelled"
    exit 0
fi

# Set permissions on directories
echo "🗂️ Setting directory permissions..."
if find "$TARGET_DIR" -type d -exec chmod "$DIR_PERMISSION" {} \;; then
    echo "✅ Directory permissions set successfully"
else
    echo "❌ Failed to set directory permissions"
    exit 1
fi

# Set permissions on files
echo "📄 Setting file permissions..."
if find "$TARGET_DIR" -type f -exec chmod "$FILE_PERMISSION" {} \;; then
    echo "✅ File permissions set successfully"
else
    echo "❌ Failed to set file permissions"
    exit 1
fi

echo "✅ Recursive permission update completed"

Enterprise Permission Management Script

#!/bin/bash

# Roundfleet Permission Management Tool
# Comprehensive file and folder permission management for enterprise environments

# Configuration
LOG_FILE="/var/log/roundfleet_permissions.log"
BACKUP_DIR="/var/backups/roundfleet/permissions"
POLICY_FILE="/etc/roundfleet/permission_policies.conf"
REPORT_DIR="/var/reports/roundfleet/permissions"

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

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

# Create permission backup
create_permission_backup() {
    local target_path="$1"
    local backup_file="$BACKUP_DIR/permissions_$(basename "$target_path")_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "📦 Creating permission backup for: $target_path"
    
    if [[ -d "$target_path" ]]; then
        # Backup directory permissions recursively
        find "$target_path" -exec ls -la {} \; > "$backup_file" 2>/dev/null
    else
        # Backup single file permissions
        ls -la "$target_path" > "$backup_file" 2>/dev/null
    fi
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Backup created: $backup_file"
        log_action "Permission backup created: $backup_file"
    else
        echo "⚠️ Warning: Could not create backup"
        log_action "Warning: Backup creation failed for $target_path"
    fi
}

# Apply enterprise permission policy
apply_enterprise_policy() {
    local policy_name="$1"
    
    echo "🏢 Applying enterprise permission policy: $policy_name"
    log_action "Starting enterprise policy application: $policy_name"
    
    case "$policy_name" in
        "secure_documents")
            apply_secure_documents_policy
            ;;
        "shared_workspace")
            apply_shared_workspace_policy
            ;;
        "application_deployment")
            apply_application_deployment_policy
            ;;
        "system_hardening")
            apply_system_hardening_policy
            ;;
        *)
            echo "❌ Unknown policy: $policy_name"
            return 1
            ;;
    esac
}

# Secure documents policy
apply_secure_documents_policy() {
    echo "🔒 Applying secure documents permission policy..."
    
    local secure_dirs=(
        "/Users/Shared/SecureDocuments"
        "/opt/roundfleet/confidential"
        "/var/secure"
    )
    
    for dir in "${secure_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            echo "Securing directory: $dir"
            
            # Create backup
            create_permission_backup "$dir"
            
            # Apply secure permissions (owner: full, group: read, others: none)
            sudo find "$dir" -type d -exec chmod 750 {} \;
            sudo find "$dir" -type f -exec chmod 640 {} \;
            
            # Set admin group ownership
            sudo chgrp -R admin "$dir"
            
            log_action "Secure permissions applied to: $dir"
        fi
    done
}

# Shared workspace policy
apply_shared_workspace_policy() {
    echo "👥 Applying shared workspace permission policy..."
    
    local shared_dirs=(
        "/Users/Shared/TeamWork"
        "/opt/roundfleet/shared"
        "/var/shared"
    )
    
    for dir in "${shared_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            echo "Configuring shared directory: $dir"
            
            # Create backup
            create_permission_backup "$dir"
            
            # Apply shared permissions (owner: full, group: full, others: read)
            sudo find "$dir" -type d -exec chmod 775 {} \;
            sudo find "$dir" -type f -exec chmod 664 {} \;
            
            # Set staff group ownership
            sudo chgrp -R staff "$dir"
            
            log_action "Shared permissions applied to: $dir"
        fi
    done
}

# Application deployment policy
apply_application_deployment_policy() {
    echo "📱 Applying application deployment permission policy..."
    
    local app_dirs=(
        "/Applications"
        "/opt/roundfleet/applications"
        "/usr/local/bin"
    )
    
    for dir in "${app_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            echo "Securing application directory: $dir"
            
            # Create backup
            create_permission_backup "$dir"
            
            # Apply application permissions (owner: full, group/others: read+execute)
            sudo find "$dir" -type d -exec chmod 755 {} \;
            sudo find "$dir" -type f -name "*.app" -exec chmod 755 {} \;
            sudo find "$dir" -type f ! -name "*.app" -exec chmod 644 {} \;
            
            # Set admin ownership
            sudo chown -R root:admin "$dir"
            
            log_action "Application permissions applied to: $dir"
        fi
    done
}

# System hardening policy
apply_system_hardening_policy() {
    echo "🛡️ Applying system hardening permission policy..."
    
    local system_dirs=(
        "/etc"
        "/var/log"
        "/usr/bin"
        "/usr/sbin"
    )
    
    for dir in "${system_dirs[@]}"; do
        if [[ -d "$dir" ]]; then
            echo "Hardening system directory: $dir"
            
            # Create backup
            create_permission_backup "$dir"
            
            # Apply restrictive permissions
            case "$dir" in
                "/etc")
                    sudo find "$dir" -type f -exec chmod 644 {} \;
                    sudo find "$dir" -type d -exec chmod 755 {} \;
                    ;;
                "/var/log")
                    sudo find "$dir" -type f -exec chmod 640 {} \;
                    sudo find "$dir" -type d -exec chmod 750 {} \;
                    ;;
                "/usr/bin"|"/usr/sbin")
                    sudo find "$dir" -type f -exec chmod 755 {} \;
                    sudo find "$dir" -type d -exec chmod 755 {} \;
                    ;;
            esac
            
            # Ensure root ownership
            sudo chown -R root:wheel "$dir"
            
            log_action "System hardening applied to: $dir"
        fi
    done
}

# Audit permission compliance
audit_permissions() {
    local target_path="$1"
    local audit_file="$REPORT_DIR/permission_audit_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "🔍 Auditing permissions for: $target_path"
    
    {
        echo "Roundfleet Permission Audit Report"
        echo "Generated: $(date)"
        echo "Target: $target_path"
        echo "Host: $(hostname)"
        echo "=================================="
        echo ""
        
        if [[ -d "$target_path" ]]; then
            echo "=== Directory Structure and Permissions ==="
            find "$target_path" -exec ls -la {} \; 2>/dev/null
            echo ""
            
            echo "=== Permission Summary ==="
            echo "Total items: $(find "$target_path" | wc -l)"
            echo "Directories: $(find "$target_path" -type d | wc -l)"
            echo "Files: $(find "$target_path" -type f | wc -l)"
            echo ""
            
            echo "=== World-Writable Files (Security Risk) ==="
            find "$target_path" -type f -perm -002 -ls 2>/dev/null || echo "None found"
            echo ""
            
            echo "=== SUID/SGID Files ==="
            find "$target_path" -type f \( -perm -4000 -o -perm -2000 \) -ls 2>/dev/null || echo "None found"
            echo ""
            
            echo "=== Files with No Owner/Group ==="
            find "$target_path" -nouser -o -nogroup 2>/dev/null || echo "None found"
            
        else
            echo "=== Single File Permissions ==="
            ls -la "$target_path"
        fi
        
    } > "$audit_file"
    
    echo "📊 Audit report saved to: $audit_file"
    log_action "Permission audit completed: $audit_file"
}

# Fix common permission issues
fix_common_issues() {
    echo "🔧 Fixing common permission issues..."
    
    # Fix world-writable files
    echo "Fixing world-writable files..."
    local world_writable
    world_writable=$(find /Users -type f -perm -002 2>/dev/null | head -10)
    
    if [[ -n "$world_writable" ]]; then
        echo "Found world-writable files:"
        echo "$world_writable"
        
        echo "$world_writable" | while read -r file; do
            if [[ -f "$file" ]]; then
                echo "Fixing: $file"
                sudo chmod o-w "$file"
                log_action "Removed world-write permission from: $file"
            fi
        done
    else
        echo "✅ No world-writable files found"
    fi
    
    # Fix common application permission issues
    echo "Fixing application permissions..."
    if [[ -d "/Applications" ]]; then
        sudo find /Applications -name "*.app" -type d -exec chmod 755 {} \; 2>/dev/null
        log_action "Fixed application permissions in /Applications"
    fi
    
    # Fix user home directory permissions
    echo "Fixing user home directory permissions..."
    for user_home in /Users/*; do
        if [[ -d "$user_home" && "$(basename "$user_home")" != "Shared" ]]; then
            username=$(basename "$user_home")
            if id "$username" &>/dev/null; then
                sudo chmod 755 "$user_home"
                sudo chown "$username:staff" "$user_home"
                log_action "Fixed home directory permissions for: $username"
            fi
        fi
    done
    
    echo "✅ Common permission issues fixed"
}

# Generate permission report
generate_permission_report() {
    local report_file="$REPORT_DIR/permission_report_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "📊 Generating comprehensive permission report..."
    
    {
        echo "Roundfleet Permission Management Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "User: $(whoami)"
        echo "======================================="
        echo ""
        
        echo "=== System Information ==="
        echo "macOS Version: $(sw_vers -productVersion)"
        echo "Build: $(sw_vers -buildVersion)"
        echo "Kernel: $(uname -r)"
        echo ""
        
        echo "=== Critical Directory Permissions ==="
        for dir in "/Applications" "/System" "/usr" "/etc" "/var"; do
            if [[ -d "$dir" ]]; then
                echo "$dir: $(ls -ld "$dir" | awk '{print $1, $3, $4}')"
            fi
        done
        echo ""
        
        echo "=== User Home Directory Permissions ==="
        for user_home in /Users/*; do
            if [[ -d "$user_home" ]]; then
                echo "$(basename "$user_home"): $(ls -ld "$user_home" | awk '{print $1, $3, $4}')"
            fi
        done
        echo ""
        
        echo "=== Security Concerns ==="
        echo "World-writable files: $(find /Users -type f -perm -002 2>/dev/null | wc -l)"
        echo "SUID files: $(find /usr -type f -perm -4000 2>/dev/null | wc -l)"
        echo "SGID files: $(find /usr -type f -perm -2000 2>/dev/null | wc -l)"
        echo ""
        
        echo "=== Recent Permission Changes ==="
        tail -20 "$LOG_FILE" 2>/dev/null || echo "No recent changes logged"
        
    } > "$report_file"
    
    echo "📊 Report saved to: $report_file"
    log_action "Permission report generated: $report_file"
}

# Main execution function
main() {
    local action="${1:-help}"
    local target="${2:-}"
    local permission="${3:-}"
    
    log_action "=== Roundfleet Permission Management Started ==="
    
    setup_directories
    
    case "$action" in
        "view")
            if [[ -n "$target" ]]; then
                audit_permissions "$target"
            else
                echo "❌ Please specify target path"
                echo "Usage: $0 view /path/to/target"
            fi
            ;;
        "set")
            if [[ -n "$target" && -n "$permission" ]]; then
                create_permission_backup "$target"
                chmod "$permission" "$target"
                log_action "Set permissions $permission on $target"
            else
                echo "❌ Please specify target and permission"
                echo "Usage: $0 set /path/to/target 755"
            fi
            ;;
        "policy")
            if [[ -n "$target" ]]; then
                apply_enterprise_policy "$target"
            else
                echo "❌ Please specify policy name"
                echo "Available policies: secure_documents, shared_workspace, application_deployment, system_hardening"
            fi
            ;;
        "audit")
            if [[ -n "$target" ]]; then
                audit_permissions "$target"
            else
                audit_permissions "/Users"
            fi
            ;;
        "fix")
            fix_common_issues
            ;;
        "report")
            generate_permission_report
            ;;
        "help"|*)
            echo "Roundfleet Permission Management Tool"
            echo "Usage: $0 [action] [target] [permission]"
            echo ""
            echo "Actions:"
            echo "  view [path]       - View permissions for path"
            echo "  set [path] [perm] - Set permissions (e.g., 755)"
            echo "  policy [name]     - Apply enterprise permission policy"
            echo "  audit [path]      - Audit permissions and security"
            echo "  fix               - Fix common permission issues"
            echo "  report            - Generate comprehensive report"
            echo "  help              - Show this help message"
            echo ""
            echo "Policies:"
            echo "  secure_documents     - Apply secure document permissions"
            echo "  shared_workspace     - Configure shared workspace permissions"
            echo "  application_deployment - Set application directory permissions"
            echo "  system_hardening     - Apply system security hardening"
            ;;
    esac
    
    log_action "=== Roundfleet Permission Management Completed ==="
}

# Execute main function
main "$@"

Common Permission Scenarios

Secure File Storage

# Create secure directory with restricted access
sudo mkdir -p /opt/roundfleet/secure
sudo chmod 700 /opt/roundfleet/secure
sudo chown root:admin /opt/roundfleet/secure

Shared Team Directory

# Create shared directory for team collaboration
sudo mkdir -p /Users/Shared/TeamProject
sudo chmod 775 /Users/Shared/TeamProject
sudo chgrp staff /Users/Shared/TeamProject

Application Deployment

# Set standard application permissions
sudo chmod 755 /Applications/MyApp.app
sudo chown root:admin /Applications/MyApp.app

Permission Reference Guide

Common Permission Patterns

Use CaseOctalSymbolicDescription
Private file600rw-------Owner read/write only
Shared file644rw-r--r--Owner write, others read
Executable755rwxr-xr-xOwner full, others read/execute
Secure directory700rwx------Owner access only
Shared directory755rwxr-xr-xOwner full, others read/list
Team directory775rwxrwxr-xOwner/group full, others read

Quick Commands Reference

# View permissions
ls -la filename
stat -f "%A %N" filename

# Set permissions
chmod 755 filename              # Octal notation
chmod u=rwx,g=rx,o=rx filename  # Symbolic notation

# Change ownership
chown user:group filename       # Change both user and group
chown user filename            # Change user only
chgrp group filename           # Change group only

# Recursive operations
chmod -R 755 directory/        # Apply to all contents
chown -R user:group directory/ # Change ownership recursively

Security Considerations

  • Principle of Least Privilege - Grant minimum necessary permissions
  • Regular Audits - Monitor permission changes and compliance
  • Backup Before Changes - Always create backups before modifications
  • World-Writable Files - Avoid or carefully control world-writable permissions
  • SUID/SGID Files - Monitor and limit special permission files
  • System Directory Protection - Maintain strict permissions on system directories

Troubleshooting

Permission Denied Errors

# Check current permissions
ls -la /path/to/file

# Check if you have sudo access
sudo -l

# Fix common permission issues
sudo chmod +r /path/to/file    # Add read permission
sudo chmod +x /path/to/file    # Add execute permission

Ownership Issues

# Check current ownership
ls -la /path/to/file

# Fix ownership
sudo chown $(whoami) /path/to/file    # Make current user owner
sudo chgrp staff /path/to/file        # Set to staff group

Important Notes

  • Administrative privileges may be required for system files
  • Backup permissions before making changes for easy restoration
  • Test changes on individual devices before fleet deployment
  • Document permission policies for compliance and auditing
  • Monitor security with regular permission audits