Tutorial

New updates and improvements to Macfleet.

Checking if a User Exists on macOS Devices

Effective user account management is essential for maintaining access control and security in any organization. When managing multiple macOS devices, administrators need reliable methods to verify user account existence across their fleet. This guide provides shell scripts and techniques to efficiently check for user presence on macOS devices.

User verification is particularly important for:

  • Security audits and compliance
  • Access control management
  • Account provisioning and deprovisioning
  • Troubleshooting login issues
  • Fleet management and inventory

Understanding User Accounts on macOS

macOS manages user accounts through various mechanisms:

  • Local user accounts: Created directly on the Mac
  • Network accounts: Managed through directory services (Active Directory, LDAP)
  • Apple ID accounts: Connected to iCloud services
  • Service accounts: System-level accounts for specific services

Each user account has unique identifiers including username, User ID (UID), and group memberships that can be verified programmatically.

Prerequisites

Before implementing these scripts, ensure you have:

  • Administrative access to the Mac devices
  • Terminal or SSH access
  • Basic understanding of bash scripting
  • macOS 10.14 or later (script compatibility)

Basic User Existence Check

The fundamental script to check if a user exists on macOS:

#!/bin/bash

# Basic user existence check
if id -u "User" >/dev/null 2>&1; then
    echo "Yes, the user exists."
else
    echo "No, the user does not exist."
fi

How this script works:

  1. id -u "User": The id command with the -u option returns the User ID (UID) of the specified username
  2. >/dev/null 2>&1: Redirects both standard output and error messages to /dev/null to suppress them
  3. Exit status check: If the user exists, id returns exit status 0 (success), otherwise it returns non-zero (failure)
  4. Conditional execution: The if statement executes different blocks based on the exit status

Enhanced User Verification Script

Here's a more comprehensive script that provides detailed user information:

#!/bin/bash

# Enhanced user verification with detailed information
USERNAME="$1"

if [ -z "$USERNAME" ]; then
    echo "Usage: $0 <username>"
    echo "Example: $0 john.doe"
    exit 1
fi

echo "Checking user: $USERNAME"
echo "================================"

if id -u "$USERNAME" >/dev/null 2>&1; then
    echo "✓ User exists"
    
    # Get user details
    USER_ID=$(id -u "$USERNAME")
    GROUP_ID=$(id -g "$USERNAME")
    USER_GROUPS=$(id -Gn "$USERNAME")
    HOME_DIR=$(eval echo ~$USERNAME)
    
    echo "User ID (UID): $USER_ID"
    echo "Primary Group ID (GID): $GROUP_ID"
    echo "Group memberships: $USER_GROUPS"
    echo "Home directory: $HOME_DIR"
    
    # Check if home directory exists
    if [ -d "$HOME_DIR" ]; then
        echo "✓ Home directory exists"
        echo "Home directory size: $(du -sh "$HOME_DIR" 2>/dev/null | cut -f1)"
    else
        echo "✗ Home directory does not exist"
    fi
    
    # Check if user is currently logged in
    if who | grep -q "^$USERNAME "; then
        echo "✓ User is currently logged in"
    else
        echo "- User is not currently logged in"
    fi
    
else
    echo "✗ User does not exist"
    echo "Available users:"
    dscl . -list /Users | grep -v "^_" | head -10
fi

Batch User Verification

For checking multiple users at once:

#!/bin/bash

# Batch user verification script
USERS=("john.doe" "jane.smith" "admin" "test.user")

echo "Batch User Verification Report"
echo "=============================="
echo "Date: $(date)"
echo ""

for username in "${USERS[@]}"; do
    if id -u "$username" >/dev/null 2>&1; then
        user_id=$(id -u "$username")
        echo "✓ $username (UID: $user_id) - EXISTS"
    else
        echo "✗ $username - DOES NOT EXIST"
    fi
done

echo ""
echo "Verification complete."

Advanced User Management Scripts

Script to List All Users

#!/bin/bash

# List all users on the system
echo "System Users Report"
echo "==================="
echo ""

echo "Regular Users (UID >= 500):"
echo "----------------------------"
dscl . -list /Users UniqueID | awk '$2 >= 500 {print $1 " (UID: " $2 ")"}' | sort -n -k3

echo ""
echo "System Users (UID < 500):"
echo "-------------------------"
dscl . -list /Users UniqueID | awk '$2 < 500 {print $1 " (UID: " $2 ")"}' | sort -n -k3

echo ""
echo "Currently Logged In Users:"
echo "-------------------------"
who | awk '{print $1}' | sort | uniq

Script to Check User Account Status

#!/bin/bash

# Check comprehensive user account status
USERNAME="$1"

if [ -z "$USERNAME" ]; then
    echo "Usage: $0 <username>"
    exit 1
fi

echo "Comprehensive User Status: $USERNAME"
echo "===================================="

if id -u "$USERNAME" >/dev/null 2>&1; then
    echo "✓ User account exists"
    
    # Check if account is enabled
    if dscl . -read /Users/$USERNAME AuthenticationAuthority 2>/dev/null | grep -q "DisabledUser"; then
        echo "✗ Account is DISABLED"
    else
        echo "✓ Account is ENABLED"
    fi
    
    # Check password policy
    pwpolicy -u "$USERNAME" -getaccountpolicies 2>/dev/null | grep -q "policyCategories" && echo "✓ Password policy applied" || echo "- No specific password policy"
    
    # Check admin privileges
    if groups "$USERNAME" | grep -q "admin"; then
        echo "⚠ User has ADMIN privileges"
    else
        echo "✓ User has standard privileges"
    fi
    
    # Check last login
    last -1 "$USERNAME" | head -1 | grep -q "wtmp begins" && echo "- No login history found" || echo "Last login: $(last -1 "$USERNAME" | head -1 | awk '{print $4, $5, $6, $7}')"
    
else
    echo "✗ User account does not exist"
fi

Remote User Verification

For managing multiple Mac devices remotely:

#!/bin/bash

# Remote user verification across multiple Macs
HOSTS=(
    "mac1.local"
    "mac2.local"
    "mac3.local"
)

USERNAME="$1"

if [ -z "$USERNAME" ]; then
    echo "Usage: $0 <username>"
    echo "Example: $0 john.doe"
    exit 1
fi

echo "Remote User Verification: $USERNAME"
echo "=================================="
echo ""

for host in "${HOSTS[@]}"; do
    echo "Checking $host..."
    
    if ping -c 1 -W 1000 "$host" >/dev/null 2>&1; then
        # Create a simple check script
        check_script="if id -u '$USERNAME' >/dev/null 2>&1; then echo 'EXISTS'; else echo 'NOT_FOUND'; fi"
        
        result=$(ssh -o ConnectTimeout=5 -o BatchMode=yes "$host" "$check_script" 2>/dev/null)
        
        if [ "$result" = "EXISTS" ]; then
            echo "  ✓ $host - User exists"
        elif [ "$result" = "NOT_FOUND" ]; then
            echo "  ✗ $host - User not found"
        else
            echo "  ⚠ $host - Unable to verify (SSH error)"
        fi
    else
        echo "  ✗ $host - Host unreachable"
    fi
done

Automated Reporting

Create automated reports for user account management:

#!/bin/bash

# Automated user existence report
REPORT_FILE="user_report_$(date +%Y%m%d_%H%M%S).txt"
USERS_TO_CHECK=("admin" "guest" "support" "developer")

{
    echo "User Existence Report"
    echo "===================="
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo "macOS Version: $(sw_vers -productVersion)"
    echo ""
    
    echo "User Verification Results:"
    echo "-------------------------"
    
    for user in "${USERS_TO_CHECK[@]}"; do
        if id -u "$user" >/dev/null 2>&1; then
            uid=$(id -u "$user")
            gid=$(id -g "$user")
            groups=$(id -Gn "$user")
            echo "✓ $user - EXISTS (UID: $uid, GID: $gid, Groups: $groups)"
        else
            echo "✗ $user - NOT FOUND"
        fi
    done
    
    echo ""
    echo "All Local Users:"
    echo "---------------"
    dscl . -list /Users UniqueID | awk '$2 >= 500 {print $1 " (UID: " $2 ")"}' | sort -n -k3
    
} > "$REPORT_FILE"

echo "Report generated: $REPORT_FILE"

Best Practices

1. Error Handling

Always include proper error handling in your scripts:

#!/bin/bash

# Robust user check with error handling
check_user() {
    local username="$1"
    
    if [ -z "$username" ]; then
        echo "ERROR: Username not provided" >&2
        return 1
    fi
    
    if id -u "$username" >/dev/null 2>&1; then
        echo "User '$username' exists"
        return 0
    else
        echo "User '$username' does not exist"
        return 1
    fi
}

# Usage
check_user "$1" || exit 1

2. Logging

Implement comprehensive logging:

#!/bin/bash

# User check with logging
LOG_FILE="/var/log/user_verification.log"

log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

USERNAME="$1"
log_message "Starting user verification for: $USERNAME"

if id -u "$USERNAME" >/dev/null 2>&1; then
    log_message "SUCCESS: User $USERNAME exists"
    echo "User exists"
else
    log_message "INFO: User $USERNAME does not exist"
    echo "User does not exist"
fi

3. Security Considerations

  • Run scripts with minimal required privileges
  • Validate input to prevent injection attacks
  • Use secure methods for remote execution
  • Implement audit trails for compliance

Troubleshooting

Common Issues

  1. Permission Denied: Ensure the script has appropriate permissions and is run by a user with sufficient privileges
  2. Command Not Found: Verify that required commands (id, dscl) are available
  3. Network Issues: For remote verification, ensure SSH keys are properly configured
  4. Directory Service Issues: Check connectivity to domain controllers for network accounts

Debugging

Add debugging to your scripts:

#!/bin/bash

# Enable debugging
set -x

# Your script here
USERNAME="$1"
echo "Debug: Checking user $USERNAME"

if id -u "$USERNAME" >/dev/null 2>&1; then
    echo "Debug: User exists"
else
    echo "Debug: User does not exist"
fi

Compatibility Notes

  • macOS 10.14 and later: Full script compatibility
  • Earlier versions: Some dscl commands may have different syntax
  • Network accounts: May require additional configuration for directory services
  • Managed accounts: Consider Mobile Device Management (MDM) policies

Conclusion

Verifying user existence on macOS devices is a fundamental aspect of system administration and security management. The scripts provided in this guide offer various approaches from simple existence checks to comprehensive user auditing.

Regular user verification helps maintain security, ensures compliance, and provides valuable insights into your Mac fleet's user landscape. Implement these scripts as part of your regular maintenance routines to keep your macOS environment secure and well-managed.

Remember to test all scripts in a controlled environment before deploying them across your fleet, and always maintain proper backup and recovery procedures when making system changes.

Check App Code Signature on macOS

Learn how to verify application code signatures on Mac devices to ensure authenticity and detect tampering. This is essential for security auditing and compliance in enterprise environments.

Basic Code Signature Check

Display detailed code signature information for an application:

#!/bin/bash

# Basic code signature verification
APP_PATH="/Applications/Safari.app"

echo "Checking code signature for: $APP_PATH"
codesign -dv --verbose=4 "$APP_PATH"

Quick Validity Check

Verify if an application is valid and meets signing requirements:

#!/bin/bash

# Quick validity check
APP_PATH="/Applications/Calendar.app"

echo "Validating: $APP_PATH"
codesign -v --verbose "$APP_PATH"

if [ $? -eq 0 ]; then
    echo "✓ Application is valid and properly signed"
else
    echo "✗ Application signature is invalid or tampered"
fi

Enhanced Code Signature Analyzer

Script with comprehensive signature analysis and error handling:

#!/bin/bash

# Function to check code signature
check_code_signature() {
    local app_path="$1"
    
    if [[ ! -d "$app_path" ]]; then
        echo "Error: Application not found at $app_path"
        return 1
    fi
    
    echo "=== Code Signature Analysis ==="
    echo "Application: $app_path"
    echo "Date: $(date)"
    echo "================================"
    
    # Detailed signature information
    echo "📋 Detailed Signature Info:"
    codesign -dv --verbose=4 "$app_path" 2>&1
    
    echo ""
    echo "🔍 Validation Check:"
    
    # Validity check
    if codesign -v --verbose "$app_path" 2>&1; then
        echo "✅ Status: VALID - Application is properly signed"
        return 0
    else
        echo "❌ Status: INVALID - Application signature compromised"
        return 1
    fi
}

# Example usage
APP_PATH="${1:-/Applications/Safari.app}"
check_code_signature "$APP_PATH"

Multiple Apps Security Scanner

Scan multiple applications for signature integrity:

#!/bin/bash

# Applications to scan
APPS_TO_SCAN=(
    "/Applications/Safari.app"
    "/Applications/Calendar.app"
    "/Applications/Mail.app"
    "/System/Applications/Calculator.app"
    "/System/Applications/TextEdit.app"
)

# Function to scan single app
scan_app() {
    local app_path="$1"
    local app_name=$(basename "$app_path" .app)
    
    echo -n "Scanning $app_name... "
    
    if [[ ! -d "$app_path" ]]; then
        echo "❓ NOT FOUND"
        return 1
    fi
    
    if codesign -v "$app_path" 2>/dev/null; then
        echo "✅ VALID"
        return 0
    else
        echo "❌ INVALID"
        
        # Show details for invalid signatures
        echo "   Details:"
        codesign -v --verbose "$app_path" 2>&1 | sed 's/^/   /'
        return 1
    fi
}

# Security scan report
echo "=== MacFleet Security Scan Report ==="
echo "Generated: $(date)"
echo "Device: $(hostname)"
echo "======================================"

valid_count=0
invalid_count=0
missing_count=0

for app_path in "${APPS_TO_SCAN[@]}"; do
    if scan_app "$app_path"; then
        ((valid_count++))
    elif [[ ! -d "$app_path" ]]; then
        ((missing_count++))
    else
        ((invalid_count++))
    fi
done

echo "======================================"
echo "📊 Summary:"
echo "   Valid signatures: $valid_count"
echo "   Invalid signatures: $invalid_count"
echo "   Missing applications: $missing_count"

if [[ $invalid_count -gt 0 ]]; then
    echo ""
    echo "⚠️  WARNING: $invalid_count application(s) have invalid signatures"
    echo "   Recommend investigating potentially tampered applications"
fi

Enterprise Code Signature Audit

Comprehensive audit script for enterprise environments:

#!/bin/bash

# Function to get signature details
get_signature_details() {
    local app_path="$1"
    
    # Get signing authority
    local authority=$(codesign -dv "$app_path" 2>&1 | grep "Authority=" | head -1 | cut -d'=' -f2)
    
    # Get hash type
    local hash_type=$(codesign -dv "$app_path" 2>&1 | grep "Hash type=" | cut -d'=' -f2)
    
    # Get timestamp
    local timestamp=$(codesign -dv "$app_path" 2>&1 | grep "Timestamp=" | cut -d'=' -f2)
    
    echo "Authority: ${authority:-Unknown}"
    echo "Hash Type: ${hash_type:-Unknown}"
    echo "Timestamp: ${timestamp:-None}"
}

# Function for enterprise audit
enterprise_audit() {
    local app_path="$1"
    local app_name=$(basename "$app_path" .app)
    
    echo "🔐 Auditing: $app_name"
    echo "Path: $app_path"
    
    if [[ ! -d "$app_path" ]]; then
        echo "Status: ❓ APPLICATION NOT FOUND"
        return 1
    fi
    
    # Perform validation
    if codesign -v "$app_path" 2>/dev/null; then
        echo "Status: ✅ VALID SIGNATURE"
        get_signature_details "$app_path"
    else
        echo "Status: ❌ INVALID SIGNATURE"
        echo "Security Risk: HIGH"
        
        # Show detailed error
        echo "Error Details:"
        codesign -v --verbose "$app_path" 2>&1 | sed 's/^/  /'
        
        # Check for added files
        echo "Checking for unauthorized modifications..."
        codesign -v --verbose "$app_path" 2>&1 | grep "file added" | sed 's/^/  🚨 /'
    fi
    
    echo "─────────────────────────────────────"
}

# Enterprise audit execution
echo "🏢 MacFleet Enterprise Security Audit"
echo "====================================="

# Audit critical system applications
CRITICAL_APPS=(
    "/Applications/Safari.app"
    "/System/Applications/Finder.app"
    "/Applications/Calendar.app"
    "/Applications/Mail.app"
)

for app in "${CRITICAL_APPS[@]}"; do
    enterprise_audit "$app"
done

echo "Audit completed: $(date)"

Usage with MacFleet

  1. Specify the application path in the script
  2. Choose between detailed analysis or quick validation
  3. Deploy through MacFleet's remote script execution
  4. Review results in action history for security compliance

Common Application Paths

ApplicationPath
Safari/Applications/Safari.app
Finder/System/Applications/Finder.app
Calendar/Applications/Calendar.app
Mail/Applications/Mail.app
Calculator/System/Applications/Calculator.app

Interpreting Results

Valid Signature: Application is authentic and unmodified

/Applications/Safari.app: valid on disk
/Applications/Safari.app: satisfies its Designated Requirement

Invalid Signature: Application has been tampered with

/Applications/Safari.app: a sealed resource is missing or invalid
file added: /Applications/Safari.app/Contents/maliciousfile.sh

Security Considerations

  • Regular audits: Schedule periodic signature checks for critical applications
  • Investigate anomalies: Any invalid signatures require immediate investigation
  • Quarantine suspicious apps: Isolate applications with compromised signatures
  • Document findings: Maintain audit trails for compliance purposes

Troubleshooting

Permission denied: Ensure script has necessary file system access Application not found: Verify the correct application path Command not found: codesign is available on all macOS systems


Note: Invalid signatures indicate potential security risks. Investigate and remediate any applications with compromised signatures immediately.

Certificate Distribution and Management on macOS

Efficiently distribute and manage security certificates across your MacFleet devices using automated command-line tools. This tutorial covers certificate deployment, validation, trust management, and enterprise CA integration.

Understanding macOS Certificate Management

macOS uses several certificate stores and trust policies:

  • System Keychain - System-wide trusted certificates
  • Login Keychain - User-specific certificates
  • Trust Settings - Certificate trust policies and validation rules
  • Certificate Authority - Root and intermediate CA certificates

Basic Certificate Distribution

Download and Install Certificate

#!/bin/bash

# Basic certificate installation from URL
CERT_URL="https://your-domain.com/certificates/company-ca.crt"
CERT_NAME="company-ca.crt"

# Download certificate
curl -O "$CERT_URL"

# Add to system keychain with trust
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "/Users/$CERT_NAME"

echo "Certificate installed successfully"

Install Local Certificate

#!/bin/bash

# Install certificate from local file
CERT_PATH="/path/to/certificate.crt"

if [[ -f "$CERT_PATH" ]]; then
    sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$CERT_PATH"
    echo "Local certificate installed successfully"
else
    echo "Certificate file not found: $CERT_PATH"
    exit 1
fi

Enterprise Certificate Management Script

#!/bin/bash

# MacFleet Certificate Distribution and Management
# Deploy, validate, and manage certificates across enterprise devices

# Configuration
LOG_FILE="/var/log/macfleet_certificates.log"
BACKUP_DIR="/var/backups/certificates"
CERT_STORE_DIR="/Library/Keychains"
TEMP_DIR="/tmp/macfleet_certs"

# Certificate sources configuration
declare -A CERTIFICATE_SOURCES=(
    ["company-root-ca"]="https://pki.company.com/certs/root-ca.crt"
    ["company-intermediate-ca"]="https://pki.company.com/certs/intermediate-ca.crt"
    ["company-ssl-ca"]="https://pki.company.com/certs/ssl-ca.crt"
)

# 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 "$BACKUP_DIR" "$TEMP_DIR"; do
        if [[ ! -d "$dir" ]]; then
            mkdir -p "$dir"
            log_action "Created directory: $dir"
        fi
    done
}

# Validate certificate file
validate_certificate() {
    local cert_file="$1"
    local cert_name="$2"
    
    log_action "Validating certificate: $cert_name"
    
    # Check if file exists and is readable
    if [[ ! -f "$cert_file" || ! -r "$cert_file" ]]; then
        log_action "ERROR: Certificate file not accessible: $cert_file"
        return 1
    fi
    
    # Validate certificate format using openssl
    if ! openssl x509 -in "$cert_file" -text -noout >/dev/null 2>&1; then
        log_action "ERROR: Invalid certificate format: $cert_name"
        return 1
    fi
    
    # Extract certificate information
    local subject
    local issuer
    local expiry
    subject=$(openssl x509 -in "$cert_file" -subject -noout | sed 's/subject=//')
    issuer=$(openssl x509 -in "$cert_file" -issuer -noout | sed 's/issuer=//')
    expiry=$(openssl x509 -in "$cert_file" -enddate -noout | sed 's/notAfter=//')
    
    log_action "Certificate Details:"
    log_action "  Subject: $subject"
    log_action "  Issuer: $issuer"
    log_action "  Expires: $expiry"
    
    # Check if certificate is expired
    if ! openssl x509 -in "$cert_file" -checkend 0 >/dev/null 2>&1; then
        log_action "WARNING: Certificate is expired: $cert_name"
        return 2
    fi
    
    # Check if certificate expires within 30 days
    if ! openssl x509 -in "$cert_file" -checkend 2592000 >/dev/null 2>&1; then
        log_action "WARNING: Certificate expires within 30 days: $cert_name"
    fi
    
    log_action "Certificate validation successful: $cert_name"
    return 0
}

# Download certificate from URL
download_certificate() {
    local cert_name="$1"
    local cert_url="$2"
    local cert_file="$TEMP_DIR/$cert_name.crt"
    
    log_action "Downloading certificate: $cert_name from $cert_url"
    
    # Download with validation
    if curl -s -f -L --connect-timeout 30 --max-time 120 -o "$cert_file" "$cert_url"; then
        log_action "Certificate downloaded successfully: $cert_name"
        echo "$cert_file"
        return 0
    else
        log_action "ERROR: Failed to download certificate: $cert_name"
        return 1
    fi
}

# Backup existing certificates
backup_certificates() {
    local backup_timestamp
    backup_timestamp=$(date '+%Y%m%d_%H%M%S')
    local backup_file="$BACKUP_DIR/keychain_backup_$backup_timestamp.tar.gz"
    
    log_action "Creating certificate backup: $backup_file"
    
    if tar -czf "$backup_file" -C /Library/Keychains . 2>/dev/null; then
        log_action "Backup created successfully: $backup_file"
        return 0
    else
        log_action "ERROR: Failed to create backup"
        return 1
    fi
}

# Install certificate to system keychain
install_certificate() {
    local cert_file="$1"
    local cert_name="$2"
    local trust_policy="${3:-trustRoot}"
    
    log_action "Installing certificate: $cert_name with trust policy: $trust_policy"
    
    # Check if certificate already exists
    if security find-certificate -c "$cert_name" /Library/Keychains/System.keychain >/dev/null 2>&1; then
        log_action "Certificate already exists in system keychain: $cert_name"
        
        # Optionally remove existing certificate
        read -p "Certificate already exists. Replace? (y/N): " -n 1 -r
        echo
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            remove_certificate "$cert_name"
        else
            return 0
        fi
    fi
    
    # Install certificate
    if sudo security add-trusted-cert -d -r "$trust_policy" -k /Library/Keychains/System.keychain "$cert_file"; then
        log_action "Certificate installed successfully: $cert_name"
        
        # Verify installation
        if security find-certificate -c "$cert_name" /Library/Keychains/System.keychain >/dev/null 2>&1; then
            log_action "Certificate verification successful: $cert_name"
            return 0
        else
            log_action "ERROR: Certificate verification failed: $cert_name"
            return 1
        fi
    else
        log_action "ERROR: Failed to install certificate: $cert_name"
        return 1
    fi
}

# Remove certificate from system keychain
remove_certificate() {
    local cert_name="$1"
    
    log_action "Removing certificate: $cert_name"
    
    if sudo security delete-certificate -c "$cert_name" /Library/Keychains/System.keychain 2>/dev/null; then
        log_action "Certificate removed successfully: $cert_name"
        return 0
    else
        log_action "Certificate not found or removal failed: $cert_name"
        return 1
    fi
}

# Configure authorization database
configure_authorization() {
    log_action "Configuring authorization database for certificate management"
    
    cat > "$TEMP_DIR/auth_config.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>allow-root</key>
    <true/>
    <key>authenticate-user</key>
    <true/>
    <key>class</key>
    <string>user</string>
    <key>comment</key>
    <string>Checked by the Admin framework when making changes to certain System Preferences.</string>
    <key>group</key>
    <string>admin</string>
    <key>session-owner</key>
    <false/>
    <key>shared</key>
    <true/>
</dict>
</plist>
EOF

    if sudo /usr/bin/security authorizationdb write system.preferences < "$TEMP_DIR/auth_config.plist"; then
        log_action "Authorization database configured successfully"
        return 0
    else
        log_action "ERROR: Failed to configure authorization database"
        return 1
    fi
}

# List installed certificates
list_certificates() {
    log_action "Listing installed certificates in system keychain"
    
    echo "=== System Keychain Certificates ==="
    security find-certificate -a -p /Library/Keychains/System.keychain | \
    openssl x509 -text -noout | \
    grep -E "(Subject:|Issuer:|Not After)" | \
    sed 's/^[[:space:]]*//'
    
    echo -e "\n=== Certificate Summary ==="
    local cert_count
    cert_count=$(security find-certificate -a /Library/Keychains/System.keychain | grep -c "keychain:")
    echo "Total certificates in system keychain: $cert_count"
}

# Generate certificate report
generate_certificate_report() {
    local report_file="$BACKUP_DIR/certificate_report_$(date '+%Y%m%d_%H%M%S').json"
    
    log_action "Generating certificate report: $report_file"
    
    {
        echo "{"
        echo "  \"report_date\": \"$(date -Iseconds)\","
        echo "  \"hostname\": \"$(hostname)\","
        echo "  \"system_info\": {"
        echo "    \"os_version\": \"$(sw_vers -productVersion)\","
        echo "    \"build_version\": \"$(sw_vers -buildVersion)\""
        echo "  },"
        echo "  \"certificates\": ["
        
        local first=true
        while IFS= read -r cert_hash; do
            if [[ "$first" == true ]]; then
                first=false
            else
                echo ","
            fi
            
            local cert_info
            cert_info=$(security find-certificate -a -Z /Library/Keychains/System.keychain | \
                       awk -v hash="$cert_hash" '
                       /^SHA-1 hash:/ { if ($3 == hash) found=1; next }
                       found && /^[[:space:]]*"/ { print; found=0 }')
            
            echo "    {"
            echo "      \"hash\": \"$cert_hash\","
            echo "      \"subject\": $cert_info"
            echo -n "    }"
        done < <(security find-certificate -a -Z /Library/Keychains/System.keychain | \
                 grep "SHA-1 hash:" | awk '{print $3}')
        
        echo ""
        echo "  ],"
        echo "  \"trust_settings\": $(security trust-settings-export -d /tmp/trust_settings.plist && plutil -convert json -o - /tmp/trust_settings.plist 2>/dev/null || echo 'null')"
        echo "}"
    } > "$report_file"
    
    log_action "Certificate report generated: $report_file"
    echo "$report_file"
}

# Deploy multiple certificates
deploy_certificate_bundle() {
    log_action "=== Starting certificate bundle deployment ==="
    
    local success_count=0
    local total_count=0
    local failed_certs=()
    
    for cert_name in "${!CERTIFICATE_SOURCES[@]}"; do
        total_count=$((total_count + 1))
        local cert_url="${CERTIFICATE_SOURCES[$cert_name]}"
        
        log_action "Processing certificate: $cert_name"
        
        # Download certificate
        local cert_file
        if cert_file=$(download_certificate "$cert_name" "$cert_url"); then
            
            # Validate certificate
            if validate_certificate "$cert_file" "$cert_name"; then
                
                # Install certificate
                if install_certificate "$cert_file" "$cert_name"; then
                    success_count=$((success_count + 1))
                    log_action "Successfully deployed certificate: $cert_name"
                else
                    failed_certs+=("$cert_name")
                fi
            else
                failed_certs+=("$cert_name")
            fi
            
            # Clean up temporary file
            rm -f "$cert_file"
        else
            failed_certs+=("$cert_name")
        fi
    done
    
    log_action "=== Certificate deployment summary ==="
    log_action "Total certificates: $total_count"
    log_action "Successfully deployed: $success_count"
    log_action "Failed deployments: ${#failed_certs[@]}"
    
    if [[ ${#failed_certs[@]} -gt 0 ]]; then
        log_action "Failed certificates: ${failed_certs[*]}"
    fi
    
    return $((total_count - success_count))
}

# Main execution function
main() {
    local action="${1:-deploy}"
    
    log_action "=== MacFleet Certificate Management Started ==="
    log_action "Action: $action"
    log_action "Hostname: $(hostname)"
    log_action "User: $(whoami)"
    
    # Setup
    setup_directories
    
    case "$action" in
        "deploy")
            backup_certificates
            configure_authorization
            deploy_certificate_bundle
            list_certificates
            generate_certificate_report
            ;;
        "list")
            list_certificates
            ;;
        "report")
            generate_certificate_report
            ;;
        "backup")
            backup_certificates
            ;;
        "remove")
            if [[ -n "$2" ]]; then
                remove_certificate "$2"
            else
                echo "Usage: $0 remove <certificate_name>"
                exit 1
            fi
            ;;
        *)
            echo "Usage: $0 {deploy|list|report|backup|remove}"
            echo "  deploy  - Deploy all configured certificates"
            echo "  list    - List installed certificates"
            echo "  report  - Generate certificate report"
            echo "  backup  - Backup current certificates"
            echo "  remove  - Remove specific certificate"
            exit 1
            ;;
    esac
    
    # Cleanup
    rm -rf "$TEMP_DIR"
    
    log_action "=== Certificate management completed ==="
}

# Execute main function
main "$@"

Certificate Trust Policies

macOS supports different trust policies for certificates:

Trust PolicyDescriptionUse Case
trustRootTrusted root certificateCA root certificates
trustAsRootTrust as root without usage constraintsEnterprise CA certificates
denyExplicitly deny trustRevoked or blacklisted certificates
unspecifiedUse system default trustLet system determine trust

Certificate Validation and Security

Verify Certificate Chain

#!/bin/bash

# Verify certificate chain and validation
verify_certificate_chain() {
    local cert_file="$1"
    local ca_bundle="/etc/ssl/cert.pem"
    
    echo "Verifying certificate chain..."
    
    # Basic certificate verification
    if openssl verify -CAfile "$ca_bundle" "$cert_file"; then
        echo "✅ Certificate chain is valid"
    else
        echo "❌ Certificate chain verification failed"
        return 1
    fi
    
    # Check certificate purposes
    echo "Certificate purposes:"
    openssl x509 -in "$cert_file" -purpose -noout
    
    # Extract key usage
    echo "Key usage:"
    openssl x509 -in "$cert_file" -text -noout | grep -A 5 "X509v3 Key Usage"
    
    return 0
}

Certificate Security Scan

#!/bin/bash

# Security analysis of installed certificates
security_scan_certificates() {
    echo "=== Certificate Security Scan ==="
    
    # Find weak certificates (MD5 or SHA1 signatures)
    echo "Checking for weak signature algorithms..."
    security find-certificate -a -p /Library/Keychains/System.keychain | \
    while read -r cert_pem; do
        if [[ "$cert_pem" =~ ^-----BEGIN ]]; then
            local sig_algo
            sig_algo=$(echo "$cert_pem" | openssl x509 -text -noout | grep "Signature Algorithm" | head -1)
            
            if [[ "$sig_algo" =~ (md5|sha1) ]]; then
                local subject
                subject=$(echo "$cert_pem" | openssl x509 -subject -noout)
                echo "⚠️  Weak signature found: $subject - $sig_algo"
            fi
        fi
    done
    
    # Find expiring certificates
    echo -e "\nChecking for expiring certificates..."
    security find-certificate -a -p /Library/Keychains/System.keychain | \
    while read -r cert_pem; do
        if [[ "$cert_pem" =~ ^-----BEGIN ]]; then
            if ! echo "$cert_pem" | openssl x509 -checkend 2592000 >/dev/null 2>&1; then
                local subject
                local expiry
                subject=$(echo "$cert_pem" | openssl x509 -subject -noout)
                expiry=$(echo "$cert_pem" | openssl x509 -enddate -noout)
                echo "⚠️  Expiring certificate: $subject - $expiry"
            fi
        fi
    done
    
    echo "Security scan completed"
}

Automated Certificate Renewal

#!/bin/bash

# Automated certificate renewal script
setup_certificate_renewal() {
    local renewal_script="/usr/local/bin/macfleet_cert_renewal.sh"
    local launchd_plist="/Library/LaunchDaemons/com.macfleet.cert.renewal.plist"
    
    # Create renewal script
    cat > "$renewal_script" << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/macfleet_cert_renewal.log"
exec > >(tee -a "$LOG_FILE") 2>&1

echo "$(date): Starting automated certificate renewal"

# Add your certificate renewal logic here
# This could include:
# - Checking certificate expiration dates
# - Downloading new certificates from your PKI
# - Replacing expired certificates
# - Sending alerts about upcoming renewals

echo "$(date): Certificate renewal completed"
EOF

    chmod +x "$renewal_script"
    
    # Create LaunchDaemon for scheduled execution
    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.macfleet.cert.renewal</string>
    <key>ProgramArguments</key>
    <array>
        <string>$renewal_script</string>
    </array>
    <key>StartCalendarInterval</key>
    <array>
        <dict>
            <key>Hour</key>
            <integer>2</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 "Certificate renewal automation configured"
    echo "Script: $renewal_script"
    echo "Schedule: Daily at 2:00 AM"
}

Enterprise Integration

Active Directory Certificate Services

#!/bin/bash

# Integration with Microsoft ADCS
deploy_adcs_certificates() {
    local adcs_server="$1"
    local cert_template="$2"
    
    echo "Deploying certificates from ADCS: $adcs_server"
    
    # Request certificate from ADCS
    # This would typically use certreq or similar tools
    # Implementation depends on your ADCS configuration
    
    echo "ADCS integration requires additional configuration"
    echo "Please consult your PKI administrator"
}

SCEP (Simple Certificate Enrollment Protocol)

#!/bin/bash

# SCEP certificate enrollment
enroll_scep_certificate() {
    local scep_url="$1"
    local challenge_password="$2"
    
    echo "Enrolling certificate via SCEP: $scep_url"
    
    # Generate private key
    openssl genrsa -out device.key 2048
    
    # Create certificate request
    openssl req -new -key device.key -out device.csr -subj "/CN=$(hostname)"
    
    # Note: SCEP enrollment requires additional tools like sscep
    echo "SCEP enrollment requires sscep or similar tools"
    echo "Please install appropriate SCEP client"
}

Best Practices

🔐 Security Considerations

  • Validate certificates before installation
  • Use strong trust policies appropriate for certificate purpose
  • Monitor certificate expiration dates regularly
  • Implement certificate pinning for critical applications

📋 Management Guidelines

  • Backup certificates before making changes
  • Document certificate purposes and owners
  • Use automation for large-scale deployments
  • Monitor certificate usage and validity

🔍 Troubleshooting

  • Check certificate format if installation fails
  • Verify network connectivity for downloads
  • Review trust policies if certificates aren't trusted
  • Check system logs for detailed error information

Important Notes

  • Administrative privileges required for system keychain modifications
  • Certificate validation essential for security compliance
  • Backup existing certificates before bulk operations
  • Test certificate deployment on subset of devices first
  • Monitor certificate expiration to prevent service disruptions

Cache Management and Clearing on macOS

Manage and clear various types of cache across your MacFleet devices using command-line tools. This tutorial covers system cache, browser cache, application cache, and enterprise-wide cache management policies for optimal performance and storage management.

Understanding macOS Cache System

macOS maintains several types of cache to improve system and application performance:

Cache Types

  • System Cache - Logs, diagnostic reports, temporary system files
  • User Cache - Application-specific temporary files and data
  • Browser Cache - Web browsing data, cookies, session storage
  • Application Cache - App-specific cached data and preferences
  • Font Cache - System and user font cache files

Cache Locations

  • System: /var/log/, /Library/Caches/, /System/Library/Caches/
  • User: ~/Library/Caches/, ~/Library/Application Support/
  • Browser: Browser-specific directories within user library
  • Downloads: ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV*

System Cache Management

Clear System Cache

#!/bin/bash

# Clear system-wide cache files
echo "🧹 Clearing system cache..."

# Clear system logs (with size limit for safety)
echo "Clearing system logs..."
sudo find /var/log -name "*.log" -type f -size +100M -delete 2>/dev/null
sudo find /var/log -name "*.out" -type f -size +50M -delete 2>/dev/null

# Clear system caches
echo "Clearing system caches..."
sudo rm -rf /Library/Caches/* 2>/dev/null
sudo rm -rf /System/Library/Caches/* 2>/dev/null

# Clear temporary files
echo "Clearing temporary files..."
sudo rm -rf /tmp/* 2>/dev/null
sudo rm -rf /var/tmp/* 2>/dev/null

echo "✅ System cache cleared successfully"

Clear User Cache

#!/bin/bash

# Clear current user's cache files
USER=$(whoami)
echo "🗂️ Clearing user cache for: $USER"

# Clear user caches
echo "Clearing user caches..."
rm -rf ~/Library/Caches/* 2>/dev/null

# Clear user logs
echo "Clearing user logs..."
rm -rf ~/Library/Logs/* 2>/dev/null

# Clear QuickLook thumbnails
echo "Clearing QuickLook thumbnails..."
rm -rf ~/Library/Caches/com.apple.QuickLook.thumbnailcache/* 2>/dev/null

# Clear Spotlight cache
echo "Clearing Spotlight cache..."
sudo mdutil -E / 2>/dev/null

echo "✅ User cache cleared successfully"

Browser Cache Management

Clear Safari Cache

#!/bin/bash

# Clear Safari browser cache
echo "🌐 Clearing Safari cache..."

# Check if Safari is running
if pgrep -x "Safari" > /dev/null; then
    echo "⚠️ Safari is running. Please close Safari first."
    read -p "Press Enter to continue after closing Safari..."
fi

# Clear Safari cache files
rm -rf ~/Library/Caches/com.apple.Safari/* 2>/dev/null
rm -rf ~/Library/Safari/LocalStorage/* 2>/dev/null
rm -rf ~/Library/Safari/Databases/* 2>/dev/null
rm -rf ~/Library/Safari/WebpageIcons.db 2>/dev/null

# Clear Safari downloads history
sqlite3 ~/Library/Safari/Downloads.plist "DELETE FROM Downloads;" 2>/dev/null

echo "✅ Safari cache cleared successfully"

Clear Chrome Cache

#!/bin/bash

# Clear Google Chrome browser cache
echo "🔍 Clearing Google Chrome cache..."

# Check if Chrome is installed
if [[ ! -d ~/Library/Application\ Support/Google/Chrome ]]; then
    echo "ℹ️ Google Chrome not found on this system"
    exit 0
fi

# Check if Chrome is running
if pgrep -x "Google Chrome" > /dev/null; then
    echo "⚠️ Chrome is running. Please close Chrome first."
    read -p "Press Enter to continue after closing Chrome..."
fi

# Clear Chrome cache files
rm -rf ~/Library/Application\ Support/Google/Chrome/*/Cache/* 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/GPUCache/* 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/*.ldb 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/*.log 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/Extension\ State/* 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/Session\ Storage/* 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/Current\ Session 2>/dev/null
rm -rf ~/Library/Application\ Support/Google/Chrome/*/Storage/ext/* 2>/dev/null

echo "✅ Chrome cache cleared successfully"

Clear Firefox Cache

#!/bin/bash

# Clear Mozilla Firefox browser cache
echo "🦊 Clearing Firefox cache..."

# Check if Firefox is installed
if [[ ! -d ~/Library/Application\ Support/Firefox ]]; then
    echo "ℹ️ Firefox not found on this system"
    exit 0
fi

# Check if Firefox is running
if pgrep -x "firefox" > /dev/null; then
    echo "⚠️ Firefox is running. Please close Firefox first."
    read -p "Press Enter to continue after closing Firefox..."
fi

# Find Firefox profile directories
for profile in ~/Library/Application\ Support/Firefox/Profiles/*; do
    if [[ -d "$profile" ]]; then
        echo "Clearing Firefox profile: $(basename "$profile")"
        rm -rf "$profile/cache2"/* 2>/dev/null
        rm -rf "$profile/thumbnails"/* 2>/dev/null
        rm -rf "$profile/cookies.sqlite-wal" 2>/dev/null
        rm -rf "$profile/webappsstore.sqlite" 2>/dev/null
    fi
done

echo "✅ Firefox cache cleared successfully"

Clear Opera Cache

#!/bin/bash

# Clear Opera browser cache
echo "🎭 Clearing Opera cache..."

# Check if Opera is installed
if [[ ! -d ~/Library/Application\ Support/com.operasoftware.Opera ]]; then
    echo "ℹ️ Opera not found on this system"
    exit 0
fi

# Check if Opera is running
if pgrep -x "Opera" > /dev/null; then
    echo "⚠️ Opera is running. Please close Opera first."
    read -p "Press Enter to continue after closing Opera..."
fi

# Clear Opera cache files
rm -rf ~/Library/Application\ Support/com.operasoftware.Opera/Cache/* 2>/dev/null
rm -rf ~/Library/Application\ Support/com.operasoftware.Opera/GPUCache/* 2>/dev/null
rm -rf ~/Library/Application\ Support/com.operasoftware.Opera/Session\ Storage/* 2>/dev/null

echo "✅ Opera cache cleared successfully"

Application Cache Management

Clear Application Caches

#!/bin/bash

# Clear application-specific caches
echo "📱 Clearing application caches..."

# Clear application caches in Containers
echo "Clearing containerized application caches..."
for container in ~/Library/Containers/*; do
    if [[ -d "$container/Data/Library/Caches" ]]; then
        app_name=$(basename "$container")
        echo "Clearing cache for: $app_name"
        rm -rf "$container/Data/Library/Caches"/* 2>/dev/null
    fi
done

# Clear Adobe cache
if [[ -d ~/Library/Caches/Adobe ]]; then
    echo "Clearing Adobe cache..."
    rm -rf ~/Library/Caches/Adobe/* 2>/dev/null
fi

# Clear Microsoft Office cache
if [[ -d ~/Library/Caches/Microsoft ]]; then
    echo "Clearing Microsoft Office cache..."
    rm -rf ~/Library/Caches/Microsoft/* 2>/dev/null
fi

# Clear Xcode cache
if [[ -d ~/Library/Developer/Xcode/DerivedData ]]; then
    echo "Clearing Xcode derived data..."
    rm -rf ~/Library/Developer/Xcode/DerivedData/* 2>/dev/null
fi

echo "✅ Application caches cleared successfully"

Clear Download History

#!/bin/bash

# Clear download history and quarantine database
echo "📥 Clearing download history..."

# Clear quarantine events (download history)
sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV* \
    'DELETE FROM LSQuarantineEvent' 2>/dev/null

# Clear recent items
rm -rf ~/Library/Application\ Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.RecentDocuments.sfl* 2>/dev/null
rm -rf ~/Library/Application\ Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.RecentApplications.sfl* 2>/dev/null

echo "✅ Download history cleared successfully"

Clear Terminal History

#!/bin/bash

# Clear terminal command history
echo "💻 Clearing terminal history..."

# Clear bash history
rm -rf ~/.bash_sessions/* 2>/dev/null
rm -rf ~/.bash_history 2>/dev/null

# Clear zsh history
rm -rf ~/.zsh_sessions/* 2>/dev/null
rm -rf ~/.zsh_history 2>/dev/null

# Clear other shell histories
rm -rf ~/.history 2>/dev/null
rm -rf ~/.sh_history 2>/dev/null

echo "✅ Terminal history cleared successfully"

Enterprise Cache Management Script

#!/bin/bash

# MacFleet Cache Management Tool
# Comprehensive cache management for enterprise environments

# Configuration
LOG_FILE="/var/log/macfleet_cache.log"
BACKUP_DIR="/var/backups/macfleet/cache"
REPORT_DIR="/var/reports/macfleet/cache"
CONFIG_FILE="/etc/macfleet/cache_policy.conf"

# Cache policy settings
ENABLE_SYSTEM_CACHE_CLEAR=true
ENABLE_BROWSER_CACHE_CLEAR=true
ENABLE_APP_CACHE_CLEAR=true
ENABLE_DOWNLOAD_HISTORY_CLEAR=false
ENABLE_TERMINAL_HISTORY_CLEAR=false
CACHE_SIZE_THRESHOLD_MB=1000
CACHE_AGE_DAYS=30

# 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 "$CONFIG_FILE")"; do
        if [[ ! -d "$dir" ]]; then
            sudo mkdir -p "$dir"
            log_action "Created directory: $dir"
        fi
    done
}

# Calculate cache size
calculate_cache_size() {
    local path="$1"
    if [[ -d "$path" ]]; then
        du -sm "$path" 2>/dev/null | awk '{print $1}'
    else
        echo "0"
    fi
}

# Generate cache report
generate_cache_report() {
    local report_file="$REPORT_DIR/cache_report_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "📊 Generating cache analysis report..."
    
    {
        echo "MacFleet Cache Analysis Report"
        echo "Generated: $(date)"
        echo "Hostname: $(hostname)"
        echo "User: $(whoami)"
        echo "================================="
        echo ""
        
        echo "=== System Cache Analysis ==="
        echo "System logs size: $(calculate_cache_size /var/log) MB"
        echo "System cache size: $(calculate_cache_size /Library/Caches) MB"
        echo "Temporary files size: $(calculate_cache_size /tmp) MB"
        echo ""
        
        echo "=== User Cache Analysis ==="
        echo "User cache size: $(calculate_cache_size ~/Library/Caches) MB"
        echo "User logs size: $(calculate_cache_size ~/Library/Logs) MB"
        echo "QuickLook cache size: $(calculate_cache_size ~/Library/Caches/com.apple.QuickLook.thumbnailcache) MB"
        echo ""
        
        echo "=== Browser Cache Analysis ==="
        if [[ -d ~/Library/Caches/com.apple.Safari ]]; then
            echo "Safari cache size: $(calculate_cache_size ~/Library/Caches/com.apple.Safari) MB"
        fi
        if [[ -d ~/Library/Application\ Support/Google/Chrome ]]; then
            echo "Chrome cache size: $(calculate_cache_size ~/Library/Application\ Support/Google/Chrome) MB"
        fi
        if [[ -d ~/Library/Application\ Support/Firefox ]]; then
            echo "Firefox cache size: $(calculate_cache_size ~/Library/Application\ Support/Firefox) MB"
        fi
        if [[ -d ~/Library/Application\ Support/com.operasoftware.Opera ]]; then
            echo "Opera cache size: $(calculate_cache_size ~/Library/Application\ Support/com.operasoftware.Opera) MB"
        fi
        echo ""
        
        echo "=== Application Cache Analysis ==="
        local total_app_cache=0
        for container in ~/Library/Containers/*; do
            if [[ -d "$container/Data/Library/Caches" ]]; then
                local size=$(calculate_cache_size "$container/Data/Library/Caches")
                if [[ $size -gt 10 ]]; then  # Only report if > 10MB
                    echo "$(basename "$container"): ${size} MB"
                    total_app_cache=$((total_app_cache + size))
                fi
            fi
        done
        echo "Total application cache: ${total_app_cache} MB"
        echo ""
        
        echo "=== Disk Usage Summary ==="
        echo "Available disk space: $(df -h / | awk 'NR==2{print $4}')"
        echo "Total cache estimate: $(($(calculate_cache_size ~/Library/Caches) + total_app_cache)) MB"
        
    } > "$report_file"
    
    echo "📊 Report saved to: $report_file"
    log_action "Cache report generated: $report_file"
}

# Selective cache clearing based on policy
clear_cache_selective() {
    echo "🧹 Starting selective cache clearing based on enterprise policy..."
    log_action "Starting selective cache clearing"
    
    local total_cleared=0
    
    # System cache clearing
    if [[ "$ENABLE_SYSTEM_CACHE_CLEAR" == "true" ]]; then
        echo "Clearing system cache..."
        local before_size=$(calculate_cache_size /Library/Caches)
        
        # Clear only old cache files
        find /Library/Caches -type f -mtime +$CACHE_AGE_DAYS -delete 2>/dev/null
        sudo find /var/log -name "*.log" -type f -mtime +$CACHE_AGE_DAYS -size +100M -delete 2>/dev/null
        
        local after_size=$(calculate_cache_size /Library/Caches)
        local cleared=$((before_size - after_size))
        total_cleared=$((total_cleared + cleared))
        
        log_action "System cache cleared: ${cleared} MB"
    fi
    
    # User cache clearing
    echo "Clearing user cache..."
    local before_size=$(calculate_cache_size ~/Library/Caches)
    
    # Clear old cache files only
    find ~/Library/Caches -type f -mtime +$CACHE_AGE_DAYS -delete 2>/dev/null
    find ~/Library/Logs -type f -mtime +$CACHE_AGE_DAYS -delete 2>/dev/null
    
    local after_size=$(calculate_cache_size ~/Library/Caches)
    local cleared=$((before_size - after_size))
    total_cleared=$((total_cleared + cleared))
    
    log_action "User cache cleared: ${cleared} MB"
    
    # Browser cache clearing
    if [[ "$ENABLE_BROWSER_CACHE_CLEAR" == "true" ]]; then
        echo "Clearing browser caches..."
        clear_browser_caches
        log_action "Browser caches cleared"
    fi
    
    # Application cache clearing
    if [[ "$ENABLE_APP_CACHE_CLEAR" == "true" ]]; then
        echo "Clearing application caches..."
        clear_application_caches
        log_action "Application caches cleared"
    fi
    
    # Download history clearing
    if [[ "$ENABLE_DOWNLOAD_HISTORY_CLEAR" == "true" ]]; then
        echo "Clearing download history..."
        sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV* \
            'DELETE FROM LSQuarantineEvent WHERE LSQuarantineTimeStamp < datetime("now", "-30 days")' 2>/dev/null
        log_action "Download history cleared"
    fi
    
    # Terminal history clearing
    if [[ "$ENABLE_TERMINAL_HISTORY_CLEAR" == "true" ]]; then
        echo "Clearing terminal history..."
        rm -rf ~/.bash_sessions/* 2>/dev/null
        rm -rf ~/.zsh_sessions/* 2>/dev/null
        log_action "Terminal history cleared"
    fi
    
    echo "✅ Cache clearing completed. Total cleared: ${total_cleared} MB"
    log_action "Cache clearing completed: ${total_cleared} MB cleared"
}

# Clear browser caches function
clear_browser_caches() {
    # Safari
    if [[ -d ~/Library/Caches/com.apple.Safari ]]; then
        rm -rf ~/Library/Caches/com.apple.Safari/* 2>/dev/null
    fi
    
    # Chrome
    if [[ -d ~/Library/Application\ Support/Google/Chrome ]]; then
        find ~/Library/Application\ Support/Google/Chrome -name "Cache" -type d -exec rm -rf {}/* \; 2>/dev/null
        find ~/Library/Application\ Support/Google/Chrome -name "GPUCache" -type d -exec rm -rf {}/* \; 2>/dev/null
    fi
    
    # Firefox
    for profile in ~/Library/Application\ Support/Firefox/Profiles/*; do
        if [[ -d "$profile/cache2" ]]; then
            rm -rf "$profile/cache2"/* 2>/dev/null
        fi
    done
    
    # Opera
    if [[ -d ~/Library/Application\ Support/com.operasoftware.Opera ]]; then
        rm -rf ~/Library/Application\ Support/com.operasoftware.Opera/Cache/* 2>/dev/null
    fi
}

# Clear application caches function
clear_application_caches() {
    for container in ~/Library/Containers/*; do
        if [[ -d "$container/Data/Library/Caches" ]]; then
            # Only clear if cache size is above threshold
            local cache_size=$(calculate_cache_size "$container/Data/Library/Caches")
            if [[ $cache_size -gt $CACHE_SIZE_THRESHOLD_MB ]]; then
                rm -rf "$container/Data/Library/Caches"/* 2>/dev/null
                log_action "Cleared cache for $(basename "$container"): ${cache_size} MB"
            fi
        fi
    done
}

# Emergency cache clearing
emergency_cache_clear() {
    echo "🚨 Emergency cache clearing - freeing maximum space..."
    log_action "Emergency cache clearing initiated"
    
    # Clear all user caches aggressively
    rm -rf ~/Library/Caches/* 2>/dev/null
    rm -rf ~/Library/Logs/* 2>/dev/null
    
    # Clear all browser data
    rm -rf ~/Library/Application\ Support/Google/Chrome/*/Cache/* 2>/dev/null
    rm -rf ~/Library/Application\ Support/Google/Chrome/*/GPUCache/* 2>/dev/null
    rm -rf ~/Library/Caches/com.apple.Safari/* 2>/dev/null
    rm -rf ~/Library/Application\ Support/Firefox/Profiles/*/cache2/* 2>/dev/null
    
    # Clear all application caches
    for container in ~/Library/Containers/*; do
        rm -rf "$container/Data/Library/Caches"/* 2>/dev/null
    done
    
    # Clear system caches (with sudo)
    sudo rm -rf /Library/Caches/* 2>/dev/null
    sudo rm -rf /tmp/* 2>/dev/null
    
    # Clear font caches
    sudo atsutil databases -remove 2>/dev/null
    
    echo "✅ Emergency cache clearing completed"
    log_action "Emergency cache clearing completed"
}

# Schedule automatic cache clearing
schedule_cache_clearing() {
    local schedule_type="$1"
    
    echo "📅 Setting up automatic cache clearing schedule..."
    
    local plist_file="$HOME/Library/LaunchAgents/com.macfleet.cache-cleaner.plist"
    
    case "$schedule_type" in
        "daily")
            local interval=86400  # 24 hours
            ;;
        "weekly")
            local interval=604800  # 7 days
            ;;
        "monthly")
            local interval=2592000  # 30 days
            ;;
        *)
            echo "❌ Invalid schedule type. Use: daily, weekly, monthly"
            return 1
            ;;
    esac
    
    cat > "$plist_file" << 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.macfleet.cache-cleaner</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>$(realpath "$0")</string>
        <string>clear</string>
    </array>
    <key>StartInterval</key>
    <integer>$interval</integer>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    launchctl load "$plist_file" 2>/dev/null
    
    echo "✅ Automatic cache clearing scheduled ($schedule_type)"
    log_action "Cache clearing scheduled: $schedule_type"
}

# Main execution function
main() {
    local action="${1:-help}"
    local target="${2:-}"
    
    log_action "=== MacFleet Cache Management Started ==="
    
    setup_directories
    
    case "$action" in
        "analyze"|"report")
            generate_cache_report
            ;;
        "clear")
            clear_cache_selective
            ;;
        "emergency")
            emergency_cache_clear
            ;;
        "schedule")
            if [[ -n "$target" ]]; then
                schedule_cache_clearing "$target"
            else
                echo "❌ Please specify schedule type"
                echo "Usage: $0 schedule [daily|weekly|monthly]"
            fi
            ;;
        "system")
            echo "🧹 Clearing system cache only..."
            sudo rm -rf /Library/Caches/* 2>/dev/null
            sudo find /var/log -name "*.log" -type f -size +100M -delete 2>/dev/null
            ;;
        "user")
            echo "🗂️ Clearing user cache only..."
            rm -rf ~/Library/Caches/* 2>/dev/null
            rm -rf ~/Library/Logs/* 2>/dev/null
            ;;
        "browser")
            echo "🌐 Clearing browser cache only..."
            clear_browser_caches
            ;;
        "apps")
            echo "📱 Clearing application cache only..."
            clear_application_caches
            ;;
        "help"|*)
            echo "MacFleet Cache Management Tool"
            echo "Usage: $0 [action] [options]"
            echo ""
            echo "Actions:"
            echo "  analyze           - Generate cache analysis report"
            echo "  clear             - Clear cache based on enterprise policy"
            echo "  emergency         - Emergency cache clearing (maximum space)"
            echo "  schedule [type]   - Schedule automatic cache clearing"
            echo "  system            - Clear system cache only"
            echo "  user              - Clear user cache only"
            echo "  browser           - Clear browser cache only"
            echo "  apps              - Clear application cache only"
            echo "  help              - Show this help message"
            echo ""
            echo "Schedule Types:"
            echo "  daily             - Clear cache daily"
            echo "  weekly            - Clear cache weekly"
            echo "  monthly           - Clear cache monthly"
            ;;
    esac
    
    log_action "=== MacFleet Cache Management Completed ==="
}

# Execute main function
main "$@"

Cache Management Best Practices

Safe Cache Clearing Guidelines

Cache TypeSafety LevelRecommendation
System CacheHigh RiskClear selectively, avoid critical system files
User CacheMedium RiskSafe to clear, may reset preferences
Browser CacheLow RiskSafe to clear, will re-download web content
Application CacheMedium RiskCheck app-specific requirements
Download HistoryLow RiskConsider privacy implications

Performance Impact Assessment

# Measure cache clearing impact
echo "=== Before Cache Clearing ==="
echo "Available space: $(df -h / | awk 'NR==2{print $4}')"
echo "Cache size: $(du -sh ~/Library/Caches | awk '{print $1}')"

# Perform cache clearing
# ... cache clearing commands ...

echo "=== After Cache Clearing ==="
echo "Available space: $(df -h / | awk 'NR==2{print $4}')"
echo "Space recovered: [calculated difference]"

Security Considerations

  • Data Loss Prevention - Always backup important data before clearing caches
  • Application Impact - Some applications may need to rebuild caches after clearing
  • Performance Impact - Initial performance may be slower until caches rebuild
  • Privacy Implications - Clearing browser cache removes saved passwords and settings
  • System Stability - Avoid clearing critical system caches without proper testing

Troubleshooting

Cache Clearing Failures

# Check for locked files
lsof | grep "Library/Caches"

# Force quit applications using cache
sudo pkill -f "application_name"

# Check permissions
ls -la ~/Library/Caches/

Disk Space Not Freed

# Force filesystem update
sync

# Check for hidden files
ls -la ~/Library/Caches/

# Verify actual deletion
du -sh ~/Library/Caches/

Important Notes

  • Backup Important Data before running cache clearing scripts
  • Close Applications before clearing their specific caches
  • Test Scripts on individual devices before fleet deployment
  • Monitor Performance after cache clearing for any issues
  • Schedule Regular Cleaning to maintain optimal performance
  • Document Policies for compliance and auditing purposes

Browser Data Management and Privacy Compliance on macOS

Implement comprehensive browser data management and privacy compliance across your MacFleet devices. This tutorial covers multi-browser data clearing, privacy policy enforcement, data retention management, and automated compliance workflows for enterprise environments.

Understanding Browser Data Management

Browser data encompasses various types of user information:

  • Browsing history - Website visit records and timestamps
  • Cookies and local storage - Session data and user preferences
  • Cache files - Temporary web content and resources
  • Download history - File download records and metadata
  • Form data and passwords - Autofill information and credentials
  • Extensions and settings - Browser configuration and add-ons

Basic Browser History Clearing

Clear Google Chrome History

#!/bin/bash

# Clear Google Chrome browsing history
clear_chrome_history() {
    echo "=== Clearing Google Chrome History ==="
    
    # Get logged-in user
    local logged_user
    logged_user=$(stat -f%Su /dev/console 2>/dev/null)
    
    if [[ -z "$logged_user" || "$logged_user" == "root" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Target user: $logged_user"
    
    # Chrome profile path
    local chrome_profile="/Users/$logged_user/Library/Application Support/Google/Chrome/Default"
    
    # Check if Chrome is installed and profile exists
    if [[ ! -d "$chrome_profile" ]]; then
        echo "⚠️  Chrome profile not found for user: $logged_user"
        return 1
    fi
    
    # Kill Chrome processes if running
    pkill -f "Google Chrome" 2>/dev/null
    sleep 2
    
    # Clear history file
    if sudo -u "$logged_user" rm -f "$chrome_profile/History" 2>/dev/null; then
        echo "✅ Chrome history cleared for user: $logged_user"
    else
        echo "❌ Failed to clear Chrome history"
        return 1
    fi
    
    return 0
}

# Execute function
clear_chrome_history

Clear Firefox History

#!/bin/bash

# Clear Firefox browsing history
clear_firefox_history() {
    echo "=== Clearing Firefox History ==="
    
    # Get logged-in user
    local logged_user
    logged_user=$(stat -f%Su /dev/console 2>/dev/null)
    
    if [[ -z "$logged_user" || "$logged_user" == "root" ]]; then
        echo "❌ No active user session found"
        return 1
    fi
    
    echo "👤 Target user: $logged_user"
    
    # Firefox profiles path
    local firefox_profiles="/Users/$logged_user/Library/Application Support/Firefox/Profiles"
    
    # Check if Firefox profiles exist
    if [[ ! -d "$firefox_profiles" ]]; then
        echo "⚠️  Firefox profiles not found for user: $logged_user"
        return 1
    fi
    
    # Kill Firefox processes if running
    pkill -f "firefox" 2>/dev/null
    sleep 2
    
    # Clear history from all Firefox profiles
    local profiles_cleared=0
    for profile_dir in "$firefox_profiles"/*; do
        if [[ -d "$profile_dir" ]]; then
            # Remove places.sqlite (contains history)
            if sudo -u "$logged_user" rm -f "$profile_dir/places.sqlite" 2>/dev/null; then
                profiles_cleared=$((profiles_cleared + 1))
                echo "✅ Cleared history for profile: $(basename "$profile_dir")"
            fi
        fi
    done
    
    if [[ $profiles_cleared -gt 0 ]]; then
        echo "✅ Firefox history cleared from $profiles_cleared profile(s)"
        return 0
    else
        echo "❌ Failed to clear Firefox history"
        return 1
    fi
}

# Execute function
clear_firefox_history

Enterprise Browser Data Management System

#!/bin/bash

# MacFleet Enterprise Browser Data Management System
# Comprehensive privacy compliance, data lifecycle management, and multi-browser support

# Configuration
LOG_FILE="/var/log/macfleet_browser_data.log"
CONFIG_DIR="/etc/macfleet/browser_management"
POLICIES_DIR="$CONFIG_DIR/policies"
REPORTS_DIR="$CONFIG_DIR/reports"
COMPLIANCE_DIR="$CONFIG_DIR/compliance"
BACKUP_DIR="/var/backups/browser_configs"

# Supported browsers and their data locations
declare -A BROWSER_PATHS=(
    ["chrome"]="/Library/Application Support/Google/Chrome"
    ["firefox"]="/Library/Application Support/Firefox"
    ["safari"]="/Library/Safari"
    ["edge"]="/Library/Application Support/Microsoft Edge"
    ["opera"]="/Library/Application Support/com.operasoftware.Opera"
    ["brave"]="/Library/Application Support/BraveSoftware/Brave-Browser"
    ["vivaldi"]="/Library/Application Support/Vivaldi"
)

# Browser data types and corresponding files
declare -A DATA_TYPES=(
    ["history"]="History,places.sqlite,History.db"
    ["cookies"]="Cookies,cookies.sqlite,Cookies.binarycookies"
    ["cache"]="Cache,cache2,WebKit/NetworkCache"
    ["downloads"]="Downloads,downloads.sqlite"
    ["passwords"]="Login Data,key4.db,logins.json"
    ["bookmarks"]="Bookmarks,bookmarks.sqlite,Bookmarks.plist"
    ["extensions"]="Extensions,extensions.sqlite,Extensions"
    ["settings"]="Preferences,prefs.js,com.apple.Safari.plist"
)

# Privacy policy templates
declare -A PRIVACY_POLICIES=(
    ["strict"]="clear_all_daily,no_persistent_cookies,history_retention_1day"
    ["moderate"]="clear_history_weekly,selective_cookies,history_retention_7days"
    ["lenient"]="clear_cache_monthly,allow_cookies,history_retention_30days"
    ["compliance"]="audit_all,encrypt_data,gdpr_compliance,history_retention_legal"
    ["education"]="clear_daily_schedule,safe_browsing,limited_downloads"
    ["healthcare"]="hipaa_compliant,no_data_retention,audit_all_access"
    ["finance"]="sox_compliant,encrypted_storage,detailed_audit"
)

# Compliance frameworks
declare -A COMPLIANCE_FRAMEWORKS=(
    ["gdpr"]="right_to_erasure,data_minimization,consent_required,audit_trails"
    ["hipaa"]="phi_protection,access_controls,audit_logs,encryption_required"
    ["sox"]="financial_data_protection,retention_policies,access_monitoring"
    ["coppa"]="child_privacy_protection,parental_consent,data_deletion"
    ["ccpa"]="california_privacy_rights,data_transparency,deletion_rights"
)

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

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

# Get all users with browser data
get_browser_users() {
    local users=()
    
    # Get all users with UID >= 500 (regular users)
    while IFS= read -r user; do
        local user_home
        user_home=$(dscl . read "/Users/$user" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
        
        if [[ -n "$user_home" && -d "$user_home" ]]; then
            # Check if user has any browser data
            for browser in "${!BROWSER_PATHS[@]}"; do
                local browser_path="$user_home${BROWSER_PATHS[$browser]}"
                if [[ -d "$browser_path" ]]; then
                    users+=("$user")
                    break
                fi
            done
        fi
    done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    
    printf '%s\n' "${users[@]}"
}

# Detect installed browsers for a user
detect_user_browsers() {
    local username="$1"
    local user_home
    user_home=$(dscl . read "/Users/$username" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
    
    if [[ -z "$user_home" ]]; then
        return 1
    fi
    
    local installed_browsers=()
    
    for browser in "${!BROWSER_PATHS[@]}"; do
        local browser_path="$user_home${BROWSER_PATHS[$browser]}"
        if [[ -d "$browser_path" ]]; then
            installed_browsers+=("$browser")
        fi
    done
    
    printf '%s\n' "${installed_browsers[@]}"
}

# Clear specific browser data type
clear_browser_data() {
    local username="$1"
    local browser="$2"
    local data_type="$3"
    local backup="${4:-false}"
    
    log_action "Clearing $data_type from $browser for user: $username"
    
    local user_home
    user_home=$(dscl . read "/Users/$username" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
    
    if [[ -z "$user_home" ]]; then
        log_action "❌ User not found: $username"
        return 1
    fi
    
    local browser_path="$user_home${BROWSER_PATHS[$browser]}"
    
    if [[ ! -d "$browser_path" ]]; then
        log_action "⚠️  Browser $browser not found for user: $username"
        return 1
    fi
    
    # Kill browser processes
    case "$browser" in
        "chrome")
            pkill -f "Google Chrome" 2>/dev/null
            ;;
        "firefox")
            pkill -f "firefox" 2>/dev/null
            ;;
        "safari")
            pkill -f "Safari" 2>/dev/null
            ;;
        "edge")
            pkill -f "Microsoft Edge" 2>/dev/null
            ;;
        *)
            pkill -f "$browser" 2>/dev/null
            ;;
    esac
    
    sleep 2
    
    # Get data files for this type
    local data_files="${DATA_TYPES[$data_type]}"
    IFS=',' read -ra FILES <<< "$data_files"
    
    local cleared_count=0
    
    for file_pattern in "${FILES[@]}"; do
        # Find and process matching files
        while IFS= read -r -d '' file; do
            if [[ -f "$file" || -d "$file" ]]; then
                # Backup if requested
                if [[ "$backup" == "true" ]]; then
                    backup_browser_data "$username" "$browser" "$file"
                fi
                
                # Clear the data
                if sudo -u "$username" rm -rf "$file" 2>/dev/null; then
                    cleared_count=$((cleared_count + 1))
                    log_action "✅ Cleared: $file"
                else
                    log_action "❌ Failed to clear: $file"
                fi
            fi
        done < <(find "$browser_path" -name "$file_pattern" -print0 2>/dev/null)
    done
    
    log_action "Cleared $cleared_count data files for $data_type in $browser"
    return 0
}

# Comprehensive browser data audit
audit_browser_data() {
    log_action "Starting comprehensive browser data audit"
    
    local audit_report="$REPORTS_DIR/browser_audit_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$audit_report" << EOF
{
    "audit_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)",
        "os_version": "$(sw_vers -productVersion)",
        "generator": "MacFleet Browser Data Manager"
    },
    "user_browser_data": [
EOF

    local first=true
    local total_users=0
    local users_with_data=0
    
    # Audit each user
    for user in $(get_browser_users); do
        total_users=$((total_users + 1))
        users_with_data=$((users_with_data + 1))
        
        if [[ "$first" == true ]]; then
            first=false
        else
            echo "," >> "$audit_report"
        fi
        
        local user_home
        user_home=$(dscl . read "/Users/$user" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
        
        local user_browsers
        user_browsers=$(detect_user_browsers "$user")
        
        # Analyze data for each browser
        local browser_data="["
        local browser_first=true
        
        for browser in $user_browsers; do
            if [[ "$browser_first" == true ]]; then
                browser_first=false
            else
                browser_data+=","
            fi
            
            local data_analysis
            data_analysis=$(analyze_browser_data "$user" "$browser")
            
            browser_data+="{\"browser\": \"$browser\", \"data\": $data_analysis}"
        done
        
        browser_data+="]"
        
        cat >> "$audit_report" << EOF
        {
            "username": "$user",
            "user_home": "$user_home",
            "browsers": $browser_data,
            "last_login": "$(last -1 "$user" | head -1 | awk '{print $4, $5, $6, $7}' || echo 'Never')",
            "privacy_risk_score": $(calculate_privacy_risk "$user")
        }
EOF
        
        log_action "Audited user: $user"
    done
    
    cat >> "$audit_report" << EOF
    ],
    "summary": {
        "total_users": $total_users,
        "users_with_browser_data": $users_with_data,
        "supported_browsers": $(echo "${!BROWSER_PATHS[@]}" | tr ' ' '\n' | jq -R . | jq -s .),
        "data_types_monitored": $(echo "${!DATA_TYPES[@]}" | tr ' ' '\n' | jq -R . | jq -s .)
    }
}
EOF

    log_action "✅ Browser data audit completed: $audit_report"
    echo "$audit_report"
}

# Analyze browser data for a specific user and browser
analyze_browser_data() {
    local username="$1"
    local browser="$2"
    
    local user_home
    user_home=$(dscl . read "/Users/$username" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
    local browser_path="$user_home${BROWSER_PATHS[$browser]}"
    
    local data_summary="{"
    local type_first=true
    
    for data_type in "${!DATA_TYPES[@]}"; do
        if [[ "$type_first" == true ]]; then
            type_first=false
        else
            data_summary+=","
        fi
        
        local file_count=0
        local total_size=0
        
        local data_files="${DATA_TYPES[$data_type]}"
        IFS=',' read -ra FILES <<< "$data_files"
        
        for file_pattern in "${FILES[@]}"; do
            while IFS= read -r -d '' file; do
                if [[ -f "$file" ]]; then
                    file_count=$((file_count + 1))
                    local size
                    size=$(stat -f%z "$file" 2>/dev/null || echo 0)
                    total_size=$((total_size + size))
                elif [[ -d "$file" ]]; then
                    file_count=$((file_count + 1))
                    local size
                    size=$(du -sk "$file" 2>/dev/null | awk '{print $1*1024}' || echo 0)
                    total_size=$((total_size + size))
                fi
            done < <(find "$browser_path" -name "$file_pattern" -print0 2>/dev/null)
        done
        
        data_summary+="\"$data_type\": {\"file_count\": $file_count, \"total_size_bytes\": $total_size}"
    done
    
    data_summary+="}"
    echo "$data_summary"
}

# Calculate privacy risk score for a user
calculate_privacy_risk() {
    local username="$1"
    local risk_score=0
    
    # Analyze data retention and privacy risks
    local user_browsers
    user_browsers=$(detect_user_browsers "$username")
    
    for browser in $user_browsers; do
        local data_analysis
        data_analysis=$(analyze_browser_data "$username" "$browser")
        
        # Simple risk calculation based on data volume
        local history_size
        history_size=$(echo "$data_analysis" | jq -r '.history.total_size_bytes // 0')
        
        if [[ $history_size -gt 10485760 ]]; then  # > 10MB
            risk_score=$((risk_score + 3))
        elif [[ $history_size -gt 1048576 ]]; then  # > 1MB
            risk_score=$((risk_score + 2))
        elif [[ $history_size -gt 0 ]]; then
            risk_score=$((risk_score + 1))
        fi
    done
    
    # Cap at 10
    if [[ $risk_score -gt 10 ]]; then
        risk_score=10
    fi
    
    echo "$risk_score"
}

# Apply privacy policy to users
apply_privacy_policy() {
    local policy_name="$1"
    local target_users="$2"
    
    log_action "Applying privacy policy: $policy_name"
    
    local policy_config="${PRIVACY_POLICIES[$policy_name]}"
    if [[ -z "$policy_config" ]]; then
        log_action "❌ Unknown privacy policy: $policy_name"
        return 1
    fi
    
    # Get target users
    local users=()
    if [[ -n "$target_users" ]]; then
        IFS=',' read -ra users <<< "$target_users"
    else
        while IFS= read -r user; do
            users+=("$user")
        done < <(get_browser_users)
    fi
    
    # Parse policy configuration
    IFS=',' read -ra POLICY_RULES <<< "$policy_config"
    
    for user in "${users[@]}"; do
        log_action "Applying policy '$policy_name' to user: $user"
        
        for rule in "${POLICY_RULES[@]}"; do
            case "$rule" in
                "clear_all_daily")
                    schedule_daily_cleanup "$user" "all"
                    ;;
                "clear_history_weekly")
                    schedule_weekly_cleanup "$user" "history"
                    ;;
                "clear_cache_monthly")
                    schedule_monthly_cleanup "$user" "cache"
                    ;;
                "no_persistent_cookies")
                    clear_browser_data "$user" "all" "cookies"
                    ;;
                "audit_all")
                    enable_comprehensive_audit "$user"
                    ;;
                "gdpr_compliance")
                    configure_gdpr_compliance "$user"
                    ;;
                "hipaa_compliant")
                    configure_hipaa_compliance "$user"
                    ;;
            esac
        done
        
        log_action "✅ Policy applied to user: $user"
    done
    
    return 0
}

# Schedule automated cleanup
schedule_daily_cleanup() {
    local username="$1"
    local data_type="$2"
    
    log_action "Scheduling daily cleanup for user: $username, data: $data_type"
    
    # Create LaunchAgent for user
    local launch_agent_path="/Users/$username/Library/LaunchAgents/com.macfleet.browser-cleanup.plist"
    
    cat > "$launch_agent_path" << 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.macfleet.browser-cleanup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/macfleet-browser-cleanup</string>
        <string>--user</string>
        <string>$username</string>
        <string>--data-type</string>
        <string>$data_type</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>2</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    chown "$username:staff" "$launch_agent_path"
    log_action "✅ Daily cleanup scheduled for user: $username"
}

# Generate compliance report
generate_compliance_report() {
    local framework="$1"
    
    log_action "Generating compliance report for framework: $framework"
    
    local compliance_report="$COMPLIANCE_DIR/compliance_${framework}_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$compliance_report" << EOF
{
    "compliance_metadata": {
        "timestamp": "$(date -Iseconds)",
        "framework": "$framework",
        "hostname": "$(hostname)",
        "generator": "MacFleet Browser Compliance Manager"
    },
    "compliance_assessment": {
        "framework_requirements": $(get_framework_requirements "$framework"),
        "current_status": $(assess_compliance_status "$framework"),
        "recommendations": $(generate_compliance_recommendations "$framework"),
        "risk_assessment": $(calculate_compliance_risk "$framework")
    },
    "user_compliance": [
EOF

    local first=true
    
    # Assess compliance for each user
    for user in $(get_browser_users); do
        if [[ "$first" == true ]]; then
            first=false
        else
            echo "," >> "$compliance_report"
        fi
        
        local user_compliance
        user_compliance=$(assess_user_compliance "$user" "$framework")
        
        cat >> "$compliance_report" << EOF
        {
            "username": "$user",
            "compliance_status": $user_compliance
        }
EOF
    done
    
    cat >> "$compliance_report" << EOF
    ]
}
EOF

    log_action "✅ Compliance report generated: $compliance_report"
    echo "$compliance_report"
}

# Get framework requirements
get_framework_requirements() {
    local framework="$1"
    
    case "$framework" in
        "gdpr")
            echo '{"data_minimization": true, "right_to_erasure": true, "consent_required": true, "audit_trails": true}'
            ;;
        "hipaa")
            echo '{"phi_protection": true, "access_controls": true, "audit_logs": true, "encryption_required": true}'
            ;;
        "sox")
            echo '{"financial_data_protection": true, "retention_policies": true, "access_monitoring": true}'
            ;;
        "coppa")
            echo '{"child_privacy_protection": true, "parental_consent": true, "data_deletion": true}'
            ;;
        *)
            echo '{"general_privacy": true, "basic_audit": true}'
            ;;
    esac
}

# Assess compliance status
assess_compliance_status() {
    local framework="$1"
    
    local compliance_score=0
    local total_checks=0
    
    # Check basic privacy controls
    total_checks=$((total_checks + 1))
    if [[ -f "$POLICIES_DIR/privacy_policy.conf" ]]; then
        compliance_score=$((compliance_score + 1))
    fi
    
    # Check audit logging
    total_checks=$((total_checks + 1))
    if [[ -f "$LOG_FILE" ]]; then
        compliance_score=$((compliance_score + 1))
    fi
    
    # Framework-specific checks
    case "$framework" in
        "gdpr")
            total_checks=$((total_checks + 2))
            # Check data retention policies
            if [[ -f "$POLICIES_DIR/data_retention.conf" ]]; then
                compliance_score=$((compliance_score + 1))
            fi
            # Check consent management
            if [[ -f "$POLICIES_DIR/consent_management.conf" ]]; then
                compliance_score=$((compliance_score + 1))
            fi
            ;;
        "hipaa")
            total_checks=$((total_checks + 1))
            # Check encryption
            if system_profiler SPStorageDataType | grep -q "Encrypted: Yes"; then
                compliance_score=$((compliance_score + 1))
            fi
            ;;
    esac
    
    local compliance_percentage
    compliance_percentage=$(awk "BEGIN {printf \"%.0f\", ($compliance_score/$total_checks)*100}")
    
    echo "{\"score\": $compliance_score, \"total_checks\": $total_checks, \"percentage\": $compliance_percentage, \"status\": \"$([ $compliance_percentage -ge 80 ] && echo 'compliant' || echo 'non_compliant')\"}"
}

# Assess user compliance
assess_user_compliance() {
    local username="$1"
    local framework="$2"
    
    local privacy_risk
    privacy_risk=$(calculate_privacy_risk "$username")
    
    local compliance_status="compliant"
    if [[ $privacy_risk -gt 7 ]]; then
        compliance_status="high_risk"
    elif [[ $privacy_risk -gt 4 ]]; then
        compliance_status="medium_risk"
    fi
    
    echo "{\"privacy_risk_score\": $privacy_risk, \"status\": \"$compliance_status\"}"
}

# Backup browser data before clearing
backup_browser_data() {
    local username="$1"
    local browser="$2"
    local data_path="$3"
    
    local timestamp
    timestamp=$(date '+%Y%m%d_%H%M%S')
    local backup_file="$BACKUP_DIR/browser_backup_${username}_${browser}_${timestamp}.tar.gz"
    
    if tar -czf "$backup_file" -C "$(dirname "$data_path")" "$(basename "$data_path")" 2>/dev/null; then
        log_action "✅ Browser data backed up: $backup_file"
        echo "$backup_file"
    else
        log_action "❌ Failed to backup browser data: $data_path"
        return 1
    fi
}

# Main execution function
main() {
    local action="${1:-audit}"
    local parameter="$2"
    local additional_param="$3"
    local extra_param="$4"
    
    log_action "=== MacFleet Browser Data Management Started ==="
    log_action "Action: $action"
    log_action "Parameter: ${parameter:-N/A}"
    
    setup_directories
    
    case "$action" in
        "clear")
            if [[ -z "$parameter" || -z "$additional_param" ]]; then
                echo "Usage: $0 clear <browser> <data_type> [username] [backup]"
                echo "Browsers: ${!BROWSER_PATHS[*]}"
                echo "Data types: ${!DATA_TYPES[*]}"
                exit 1
            fi
            local target_user="${extra_param:-$(stat -f%Su /dev/console 2>/dev/null)}"
            clear_browser_data "$target_user" "$parameter" "$additional_param" "${5:-false}"
            ;;
        "audit")
            audit_browser_data
            ;;
        "policy")
            if [[ -z "$parameter" ]]; then
                echo "Available privacy policies:"
                for policy in "${!PRIVACY_POLICIES[@]}"; do
                    echo "  - $policy: ${PRIVACY_POLICIES[$policy]}"
                done
                echo ""
                echo "Usage: $0 policy <policy_name> [target_users]"
                exit 1
            fi
            apply_privacy_policy "$parameter" "$additional_param"
            ;;
        "compliance")
            if [[ -z "$parameter" ]]; then
                echo "Available compliance frameworks:"
                for framework in "${!COMPLIANCE_FRAMEWORKS[@]}"; do
                    echo "  - $framework: ${COMPLIANCE_FRAMEWORKS[$framework]}"
                done
                echo ""
                echo "Usage: $0 compliance <framework>"
                exit 1
            fi
            generate_compliance_report "$parameter"
            ;;
        "detect")
            local target_user="${parameter:-$(stat -f%Su /dev/console 2>/dev/null)}"
            echo "Browsers detected for user '$target_user':"
            detect_user_browsers "$target_user"
            ;;
        *)
            echo "Usage: $0 {clear|audit|policy|compliance|detect}"
            echo "  clear       - Clear specific browser data"
            echo "  audit       - Generate comprehensive browser data audit"
            echo "  policy      - Apply privacy policy to users"
            echo "  compliance  - Generate compliance report"
            echo "  detect      - Detect installed browsers for user"
            exit 1
            ;;
    esac
    
    log_action "=== Browser data management completed ==="
}

# Execute main function
main "$@"

Advanced Browser Management Features

Multi-Browser Data Analysis

#!/bin/bash

# Comprehensive multi-browser data analysis
analyze_all_browsers() {
    echo "=== Multi-Browser Data Analysis ==="
    
    local analysis_report="$REPORTS_DIR/browser_analysis_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$analysis_report" << EOF
{
    "analysis_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)"
    },
    "browser_usage_analysis": {
EOF

    local browser_first=true
    
    # Analyze each supported browser
    for browser in "${!BROWSER_PATHS[@]}"; do
        if [[ "$browser_first" == true ]]; then
            browser_first=false
        else
            echo "," >> "$analysis_report"
        fi
        
        local users_with_browser=0
        local total_data_size=0
        
        # Count users and data size for this browser
        for user in $(get_browser_users); do
            local user_browsers
            user_browsers=$(detect_user_browsers "$user")
            
            if echo "$user_browsers" | grep -q "^$browser$"; then
                users_with_browser=$((users_with_browser + 1))
                
                local browser_data
                browser_data=$(analyze_browser_data "$user" "$browser")
                
                # Sum up data sizes
                for data_type in "${!DATA_TYPES[@]}"; do
                    local size
                    size=$(echo "$browser_data" | jq -r ".$data_type.total_size_bytes // 0")
                    total_data_size=$((total_data_size + size))
                done
            fi
        done
        
        cat >> "$analysis_report" << EOF
        "$browser": {
            "users_count": $users_with_browser,
            "total_data_size_bytes": $total_data_size,
            "average_data_per_user": $(( users_with_browser > 0 ? total_data_size / users_with_browser : 0 ))
        }
EOF
    done
    
    cat >> "$analysis_report" << EOF
    }
}
EOF

    echo "📊 Browser analysis completed: $analysis_report"
}

Automated Privacy Cleanup

#!/bin/bash

# Automated privacy cleanup based on data age and policy
automated_privacy_cleanup() {
    local retention_days="${1:-7}"
    local dry_run="${2:-false}"
    
    echo "=== Automated Privacy Cleanup ==="
    echo "Retention period: $retention_days days"
    echo "Dry run: $dry_run"
    
    local cleanup_report="$REPORTS_DIR/privacy_cleanup_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$cleanup_report" << EOF
{
    "cleanup_metadata": {
        "timestamp": "$(date -Iseconds)",
        "retention_days": $retention_days,
        "dry_run": $dry_run
    },
    "cleanup_results": [
EOF

    local first=true
    local total_cleaned=0
    
    # Process each user
    for user in $(get_browser_users); do
        local user_home
        user_home=$(dscl . read "/Users/$user" NFSHomeDirectory 2>/dev/null | awk '{print $2}')
        
        for browser in $(detect_user_browsers "$user"); do
            local browser_path="$user_home${BROWSER_PATHS[$browser]}"
            
            # Find old data files
            while IFS= read -r -d '' file; do
                local file_age_days
                file_age_days=$(( ($(date +%s) - $(stat -f%m "$file")) / 86400 ))
                
                if [[ $file_age_days -gt $retention_days ]]; then
                    if [[ "$first" == true ]]; then
                        first=false
                    else
                        echo "," >> "$cleanup_report"
                    fi
                    
                    cat >> "$cleanup_report" << EOF
        {
            "user": "$user",
            "browser": "$browser",
            "file": "$file",
            "age_days": $file_age_days,
            "action": "$([ "$dry_run" == "true" ] && echo "would_delete" || echo "deleted")"
        }
EOF
                    
                    if [[ "$dry_run" != "true" ]]; then
                        if sudo -u "$user" rm -rf "$file" 2>/dev/null; then
                            total_cleaned=$((total_cleaned + 1))
                        fi
                    fi
                fi
            done < <(find "$browser_path" -type f -print0 2>/dev/null)
        done
    done
    
    cat >> "$cleanup_report" << EOF
    ],
    "summary": {
        "total_files_processed": $total_cleaned
    }
}
EOF

    echo "🧹 Privacy cleanup completed: $cleanup_report"
}

Best Practices

🔒 Privacy and Security

  • Data minimization principles with automated cleanup policies
  • Consent management for data collection and processing
  • Encryption standards for sensitive browser data
  • Access controls with role-based data management permissions

📋 Compliance Management

  • Multi-framework support (GDPR, HIPAA, SOX, COPPA, CCPA)
  • Automated compliance assessment with regular auditing
  • Data retention policies aligned with legal requirements
  • Audit trails with comprehensive logging and reporting

🔧 Enterprise Operations

  • Fleet-wide deployment of privacy policies and data management
  • Scheduled cleanup operations with customizable retention periods
  • Backup and recovery capabilities for browser configurations
  • Integration support with existing security and compliance systems

🚀 User Experience

  • Non-disruptive operations with browser process management
  • Selective data clearing preserving important user preferences
  • Transparent reporting on data management activities
  • Flexible policy application based on user roles and requirements

Important Notes

  • Browser compatibility varies across different applications and versions
  • User data backup recommended before implementing aggressive cleanup policies
  • Performance impact minimal when operations are scheduled during off-hours
  • Legal compliance requirements vary by jurisdiction and industry
  • User notification may be required for certain data management activities
  • Regular policy review needed to adapt to changing privacy regulations