Tutorial

New updates and improvements to Roundfleet.

Date and Time Management on macOS

Manage date and time settings across your Roundfleet with enterprise-grade automation, validation controls, and comprehensive monitoring capabilities.

Understanding Enterprise Date and Time Management

Enterprise date and time management requires more than basic date setting, demanding:

  • Automated validation and formatting with enterprise-grade error handling
  • Scheduled date/time operations with business logic integration
  • Compliance tracking for audit requirements and regulatory standards
  • Real-time monitoring of date/time changes and system integrity
  • Integration capabilities with enterprise scheduling and workflow systems
  • Security controls to prevent unauthorized time manipulation

Core Date and Time Management Process

Basic Commands

  1. Set Date/Time - date MMDDhhmm[[CC]YY][.ss]
  2. Parameterized Setting - date $1 (with argument passing)

Core Date Format

The format follows: MMDDhhmm[[CC]YY][.ss]

  • MM - Month (01-12)
  • DD - Day (01-31)
  • hh - Hour (00-23)
  • mm - Minutes (00-59)
  • CC - Century (optional)
  • YY - Year (optional)
  • ss - Seconds (optional)

Basic Configuration Examples

# Basic date setting
date 120614302023.00  # December 6, 2023 2:30 PM

# Parameterized version
date $1  # Pass date as argument

Enterprise Date and Time Management System

#!/bin/bash

# Roundfleet Enterprise Date and Time Management System
# Comprehensive date/time management with enterprise controls and monitoring

# Configuration
SCRIPT_NAME="Roundfleet Date/Time Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_datetime.log"
AUDIT_LOG="/var/log/roundfleet_datetime_audit.log"
CONFIG_DIR="/etc/roundfleet/datetime"
POLICIES_DIR="/etc/roundfleet/datetime/policies"
BACKUP_DIR="/var/backups/datetime"
TEMP_DIR="/tmp/roundfleet_datetime"
ORGANIZATION_NAME="Roundfleet Enterprise"
DEPLOYMENT_MODE="enterprise"
ENABLE_VALIDATION=true
ENABLE_AUDIT_LOGGING=true
ENABLE_BACKUP_RESTORE=true
MAX_TIME_DRIFT_HOURS=24
BUSINESS_HOURS_START="08:00"
BUSINESS_HOURS_END="18:00"

# Date/Time Validation Patterns
declare -A DATE_FORMATS=(
    ["roundfleet"]="MMDDhhmm[[CC]YY][.ss]"
    ["iso8601"]="YYYY-MM-DDTHH:MM:SS"
    ["unix"]="seconds_since_epoch"
    ["readable"]="Month DD, YYYY HH:MM:SS"
)

# Enterprise Scheduling Policies
declare -A SCHEDULING_POLICIES=(
    ["immediate"]="execute_now"
    ["business_hours"]="within_business_hours_only"
    ["maintenance_window"]="scheduled_maintenance_only"
    ["emergency"]="override_all_restrictions"
)

# Compliance Standards
declare -A COMPLIANCE_REQUIREMENTS=(
    ["SOX"]="financial_audit_trail"
    ["HIPAA"]="healthcare_time_integrity"
    ["PCI_DSS"]="payment_transaction_accuracy"
    ["ISO27001"]="information_security_timestamps"
)

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

# Set secure permissions
chmod 755 "$CONFIG_DIR"
chmod 750 "$POLICIES_DIR"
chmod 750 "$BACKUP_DIR"
chmod 700 "$TEMP_DIR"

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

log_security_event() {
    local event_type="$1"
    local details="$2"
    local severity="$3"
    local admin_user=$(whoami)
    
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local source_ip=$(who am i | awk '{print $5}' | tr -d '()')
    echo "SECURITY|$timestamp|$event_type|$severity|$admin_user|$source_ip|$details" >> "$AUDIT_LOG"
}

# Get current date and time information
get_current_datetime() {
    local format="${1:-all}"
    
    echo "=== Current Date and Time Information ==="
    echo "Local Time: $(date '+%Y-%m-%d %H:%M:%S %Z')"
    echo "UTC Time: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
    echo "Unix Timestamp: $(date +%s)"
    echo "Uptime: $(uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}')"
    
    case "$format" in
        "roundfleet")
            echo "Roundfleet Format: $(date '+%m%d%H%M%Y.%S')"
            ;;
        "iso8601")
            echo "ISO 8601 Format: $(date '+%Y-%m-%dT%H:%M:%S')"
            ;;
        "detailed")
            echo ""
            echo "Detailed Information:"
            echo "  Year: $(date '+%Y')"
            echo "  Month: $(date '+%m') ($(date '+%B'))"
            echo "  Day: $(date '+%d')"
            echo "  Hour: $(date '+%H')"
            echo "  Minute: $(date '+%M')"
            echo "  Second: $(date '+%S')"
            echo "  Day of Week: $(date '+%A')"
            echo "  Day of Year: $(date '+%j')"
            echo "  Week of Year: $(date '+%U')"
            ;;
    esac
    echo ""
}

# Validate date/time format
validate_datetime_format() {
    local datetime_string="$1"
    local format_type="${2:-roundfleet}"
    
    echo "=== Date/Time Format Validation ==="
    echo "Input: $datetime_string"
    echo "Expected Format: $format_type"
    echo ""
    
    case "$format_type" in
        "roundfleet")
            # Validate Roundfleet format: MMDDhhmm[[CC]YY][.ss]
            if [[ "$datetime_string" =~ ^[0-9]{8}([0-9]{4})?(\.[0-9]{2})?$ ]]; then
                local month="${datetime_string:0:2}"
                local day="${datetime_string:2:2}"
                local hour="${datetime_string:4:2}"
                local minute="${datetime_string:6:2}"
                
                # Validate ranges
                if [[ $month -ge 1 && $month -le 12 ]] && \
                   [[ $day -ge 1 && $day -le 31 ]] && \
                   [[ $hour -ge 0 && $hour -le 23 ]] && \
                   [[ $minute -ge 0 && $minute -le 59 ]]; then
                    echo "✅ Valid Roundfleet format"
                    return 0
                else
                    echo "❌ Invalid date/time values in Roundfleet format"
                    return 1
                fi
            else
                echo "❌ Invalid Roundfleet format structure"
                echo "Expected: MMDDhhmm[[CC]YY][.ss]"
                return 1
            fi
            ;;
        "iso8601")
            # Validate ISO 8601 format
            if date -j -f "%Y-%m-%dT%H:%M:%S" "$datetime_string" &>/dev/null; then
                echo "✅ Valid ISO 8601 format"
                return 0
            else
                echo "❌ Invalid ISO 8601 format"
                return 1
            fi
            ;;
        "unix")
            # Validate Unix timestamp
            if [[ "$datetime_string" =~ ^[0-9]+$ ]] && [[ $datetime_string -gt 0 ]]; then
                echo "✅ Valid Unix timestamp"
                return 0
            else
                echo "❌ Invalid Unix timestamp"
                return 1
            fi
            ;;
        *)
            echo "❌ Unknown format type: $format_type"
            return 1
            ;;
    esac
}

# Convert between date formats
convert_datetime_format() {
    local input_datetime="$1"
    local from_format="$2"
    local to_format="$3"
    
    echo "=== Date/Time Format Conversion ==="
    echo "Input: $input_datetime"
    echo "From: $from_format"
    echo "To: $to_format"
    echo ""
    
    local converted_datetime
    
    case "$from_format" in
        "roundfleet")
            # Convert from Roundfleet format
            local month="${input_datetime:0:2}"
            local day="${input_datetime:2:2}"
            local hour="${input_datetime:4:2}"
            local minute="${input_datetime:6:2}"
            local year_part="${input_datetime:8:4}"
            local seconds_part="${input_datetime:13:2}"
            
            # Default year if not provided
            if [[ -z "$year_part" ]]; then
                year_part=$(date '+%Y')
            fi
            
            # Default seconds if not provided
            if [[ -z "$seconds_part" ]]; then
                seconds_part="00"
            fi
            
            case "$to_format" in
                "iso8601")
                    converted_datetime="${year_part}-${month}-${day}T${hour}:${minute}:${seconds_part}"
                    ;;
                "readable")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "iso8601")
            # Convert from ISO 8601 format
            case "$to_format" in
                "roundfleet")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "unix")
            # Convert from Unix timestamp
            case "$to_format" in
                "roundfleet")
                    converted_datetime=$(date -r "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "iso8601")
                    converted_datetime=$(date -r "$input_datetime" '+%Y-%m-%dT%H:%M:%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -r "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
            esac
            ;;
    esac
    
    if [[ -n "$converted_datetime" ]]; then
        echo "✅ Conversion successful"
        echo "Result: $converted_datetime"
        echo "$converted_datetime"
        return 0
    else
        echo "❌ Conversion failed"
        return 1
    fi
}

# Set date and time with enterprise validation
set_enterprise_datetime() {
    local datetime_input="$1"
    local format_type="${2:-roundfleet}"
    local policy="${3:-business_hours}"
    local force="${4:-false}"
    local admin_user=$(whoami)
    
    log_security_event "DATETIME_CHANGE_ATTEMPT" "datetime=$datetime_input,format=$format_type,policy=$policy" "INFO"
    
    echo "=== Enterprise Date/Time Configuration ==="
    echo "Input: $datetime_input"
    echo "Format: $format_type"
    echo "Policy: $policy"
    echo "Administrator: $admin_user"
    echo "Force Mode: $force"
    echo ""
    
    # Validate input format
    if ! validate_datetime_format "$datetime_input" "$format_type"; then
        log_operation "ERROR" "Invalid date/time format: $datetime_input ($format_type)"
        return 1
    fi
    
    # Check scheduling policy
    if [[ "$policy" == "business_hours" && "$force" != "true" ]]; then
        local current_hour=$(date '+%H')
        local business_start_hour="${BUSINESS_HOURS_START:0:2}"
        local business_end_hour="${BUSINESS_HOURS_END:0:2}"
        
        if [[ $current_hour -lt $business_start_hour || $current_hour -gt $business_end_hour ]]; then
            echo "⚠️  Operation requested outside business hours ($BUSINESS_HOURS_START-$BUSINESS_HOURS_END)"
            echo "Use force=true to override or wait for business hours"
            log_operation "WARNING" "Date/time change blocked by business hours policy"
            return 1
        fi
    fi
    
    # Backup current date/time
    local backup_file="$BACKUP_DIR/datetime_$(date +%Y%m%d_%H%M%S).backup"
    {
        echo "# Roundfleet Date/Time Backup"
        echo "PREVIOUS_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "PREVIOUS_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "PREVIOUS_UNIX=$(date +%s)"
        echo "BACKUP_TIMESTAMP=$(date)"
        echo "CHANGED_BY=$admin_user"
        echo "NEW_DATETIME=$datetime_input"
        echo "FORMAT_TYPE=$format_type"
        echo "POLICY=$policy"
    } > "$backup_file"
    
    log_operation "INFO" "Date/time backup created: $backup_file"
    
    # Convert to appropriate format if needed
    local roundfleet_format="$datetime_input"
    
    if [[ "$format_type" != "roundfleet" ]]; then
        echo "Converting $format_type to Roundfleet format..."
        roundfleet_format=$(convert_datetime_format "$datetime_input" "$format_type" "roundfleet")
        
        if [[ $? -ne 0 ]]; then
            log_operation "ERROR" "Failed to convert date/time format"
            return 1
        fi
        
        echo "Converted format: $roundfleet_format"
    fi
    
    # Validate time drift
    local current_unix=$(date +%s)
    local target_unix=$(convert_datetime_format "$roundfleet_format" "roundfleet" "unix")
    local time_diff=$((target_unix - current_unix))
    local time_diff_hours=$((time_diff / 3600))
    local time_diff_abs=${time_diff_hours#-}
    
    if [[ $time_diff_abs -gt $MAX_TIME_DRIFT_HOURS && "$force" != "true" ]]; then
        echo "⚠️  Large time change detected: ${time_diff_hours} hours"
        echo "This exceeds the maximum drift threshold of $MAX_TIME_DRIFT_HOURS hours"
        echo "Use force=true to override this safety check"
        log_operation "WARNING" "Large time drift blocked: ${time_diff_hours} hours"
        return 1
    fi
    
    # Apply date/time change
    echo "Setting date/time to: $roundfleet_format"
    
    if sudo date "$roundfleet_format" &>/dev/null; then
        echo "✅ Date/time set successfully"
        log_operation "INFO" "Date/time changed to: $roundfleet_format (format: $format_type)"
        log_security_event "DATETIME_CHANGED" "new_datetime=$roundfleet_format,drift_hours=$time_diff_hours,policy=$policy" "INFO"
        
        # Verify the change
        sleep 1
        echo ""
        echo "Verification:"
        get_current_datetime
        
        return 0
    else
        echo "❌ Failed to set date/time"
        log_operation "ERROR" "Failed to set date/time: $roundfleet_format"
        log_security_event "DATETIME_CHANGE_FAILED" "datetime=$roundfleet_format,error=date_command_failed" "ERROR"
        return 1
    fi
}

# Schedule date/time operations
schedule_datetime_operation() {
    local operation="$1"
    local target_datetime="$2"
    local schedule_time="$3"
    local policy="${4:-business_hours}"
    
    echo "=== Scheduled Date/Time Operation ==="
    echo "Operation: $operation"
    echo "Target DateTime: $target_datetime"
    echo "Schedule Time: $schedule_time"
    echo "Policy: $policy"
    echo ""
    
    # Create scheduled operation file
    local schedule_file="$POLICIES_DIR/scheduled_$(date +%Y%m%d_%H%M%S).sh"
    
    cat > "$schedule_file" << EOF
#!/bin/bash
# Roundfleet Scheduled Date/Time Operation
# Generated: $(date)
# Operation: $operation
# Target: $target_datetime
# Policy: $policy

# Execute the scheduled operation
case "$operation" in
    "set_datetime")
        $0 set "$target_datetime" roundfleet "$policy" true
        ;;
    "sync_time")
        sudo systemsetup -setusingnetworktime on
        ;;
    "backup_datetime")
        $0 backup
        ;;
    *)
        echo "Unknown operation: $operation"
        exit 1
        ;;
esac
EOF
    
    chmod +x "$schedule_file"
    
    # Schedule using at command (if available)
    if command -v at &>/dev/null; then
        echo "$schedule_file" | at "$schedule_time" 2>/dev/null
        
        if [[ $? -eq 0 ]]; then
            echo "✅ Operation scheduled successfully for $schedule_time"
            log_operation "INFO" "Scheduled operation: $operation at $schedule_time"
            return 0
        else
            echo "❌ Failed to schedule operation"
            log_operation "ERROR" "Failed to schedule operation: $operation"
            return 1
        fi
    else
        echo "⚠️  'at' command not available for scheduling"
        echo "Schedule file created: $schedule_file"
        echo "Execute manually or integrate with your scheduling system"
        return 1
    fi
}

# Monitor date/time integrity
monitor_datetime_integrity() {
    local check_type="${1:-basic}"
    local admin_user=$(whoami)
    
    echo "=== Date/Time Integrity Monitoring ==="
    echo "Check Type: $check_type"
    echo "Monitor: $admin_user"
    echo ""
    
    local integrity_status="HEALTHY"
    local issues=()
    
    # Check system clock vs network time
    if command -v ntpdate &>/dev/null; then
        echo "Checking time synchronization..."
        
        local ntp_time=$(ntpdate -q pool.ntp.org 2>/dev/null | tail -1 | grep -o "offset [+-][0-9.]*" | awk '{print $2}')
        
        if [[ -n "$ntp_time" ]]; then
            local offset_abs=${ntp_time#-}
            
            echo "NTP offset: ${ntp_time}s"
            
            if (( $(echo "$offset_abs > 30" | bc -l) )); then
                integrity_status="WARNING"
                issues+=("Large NTP offset: ${ntp_time}s")
            else
                echo "✅ Time synchronization within acceptable range"
            fi
        else
            integrity_status="WARNING"
            issues+=("Unable to check NTP synchronization")
        fi
    fi
    
    # Check for recent large time changes
    if [[ -f "$AUDIT_LOG" ]]; then
        echo ""
        echo "Checking recent time changes..."
        
        local recent_changes=$(grep "DATETIME_CHANGED" "$AUDIT_LOG" | tail -5)
        
        if [[ -n "$recent_changes" ]]; then
            echo "Recent date/time changes found:"
            echo "$recent_changes" | while read -r line; do
                echo "  $(echo "$line" | cut -d'|' -f2,6)"
            done
        else
            echo "✅ No recent date/time changes detected"
        fi
    fi
    
    # Advanced checks
    if [[ "$check_type" == "comprehensive" ]]; then
        echo ""
        echo "Running comprehensive integrity checks..."
        
        # Check system logs for time-related errors
        local time_errors=$(log show --predicate 'subsystem == "com.apple.time"' --last 1h 2>/dev/null | grep -i error | wc -l)
        
        if [[ $time_errors -gt 0 ]]; then
            integrity_status="WARNING"
            issues+=("System time errors detected: $time_errors")
        fi
        
        # Check for timezone mismatches
        local system_tz=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')
        local env_tz="$TZ"
        
        if [[ -n "$env_tz" && "$env_tz" != "$system_tz" ]]; then
            integrity_status="WARNING"
            issues+=("Timezone mismatch: system=$system_tz, env=$env_tz")
        fi
    fi
    
    # Generate integrity report
    echo ""
    echo "=== Date/Time Integrity Report ==="
    echo "Overall Status: $integrity_status"
    echo "Timestamp: $(date)"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "Issues Found:"
        printf '  - %s\n' "${issues[@]}"
    else
        echo "✅ All date/time systems operating normally"
    fi
    
    # Log monitoring results
    log_operation "INFO" "Date/time integrity check completed: $integrity_status (${#issues[@]} issues)"
    log_security_event "DATETIME_INTEGRITY_CHECK" "status=$integrity_status,issues=${#issues[@]}" "INFO"
    
    # Return appropriate exit code
    case "$integrity_status" in
        "HEALTHY") return 0 ;;
        "WARNING") return 1 ;;
        "CRITICAL") return 2 ;;
        *) return 3 ;;
    esac
}

# Generate date/time management report
generate_datetime_report() {
    local report_type="${1:-summary}"
    local admin_user=$(whoami)
    local report_file="/var/reports/datetime_report_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$report_file")"
    
    log_security_event "REPORT_GENERATION" "type=$report_type" "INFO"
    
    {
        echo "Roundfleet Date/Time Management Report"
        echo "==================================="
        echo "Report Type: $report_type"
        echo "Generated: $(date)"
        echo "Generated By: $admin_user"
        echo "Hostname: $(hostname)"
        echo ""
        
        case "$report_type" in
            "summary")
                echo "== Date/Time Summary =="
                get_current_datetime "detailed"
                
                echo "Available Formats:"
                for format in "${!DATE_FORMATS[@]}"; do
                    echo "  $format: ${DATE_FORMATS[$format]}"
                done
                ;;
            "compliance")
                echo "== Compliance Assessment =="
                
                echo "Compliance Standards:"
                for standard in "${!COMPLIANCE_REQUIREMENTS[@]}"; do
                    echo "  $standard: ${COMPLIANCE_REQUIREMENTS[$standard]}"
                done
                
                echo ""
                echo "Recent Audit Events:"
                if [[ -f "$AUDIT_LOG" ]]; then
                    tail -10 "$AUDIT_LOG"
                else
                    echo "No audit log available"
                fi
                ;;
            "audit")
                echo "== Audit Information =="
                if [[ -f "$AUDIT_LOG" ]]; then
                    echo "Complete audit trail:"
                    cat "$AUDIT_LOG"
                else
                    echo "No audit log available"
                fi
                ;;
        esac
        
        echo ""
        echo "== System Information =="
        echo "Uptime: $(uptime)"
        echo "Load Average: $(uptime | awk -F'load average:' '{print $2}')"
        
    } > "$report_file"
    
    echo "Date/time report generated: $report_file"
    log_operation "INFO" "Date/time report generated: $report_file"
}

# Backup and restore date/time settings
backup_datetime_settings() {
    local backup_type="${1:-full}"
    
    echo "=== Date/Time Settings Backup ==="
    echo "Backup Type: $backup_type"
    echo ""
    
    local backup_file="$BACKUP_DIR/datetime_settings_$(date +%Y%m%d_%H%M%S).backup"
    
    {
        echo "# Roundfleet Date/Time Settings Backup"
        echo "BACKUP_DATE=$(date)"
        echo "BACKUP_TYPE=$backup_type"
        echo ""
        echo "# Current Settings"
        echo "CURRENT_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "CURRENT_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "CURRENT_UNIX=$(date +%s)"
        echo "CURRENT_TIMEZONE=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')"
        echo "NETWORK_TIME=$(systemsetup -getusingnetworktime 2>/dev/null | awk -F': ' '{print $2}')"
        echo "TIME_SERVER=$(systemsetup -getnetworktimeserver 2>/dev/null | awk -F': ' '{print $2}')"
        echo ""
        echo "# System Information"
        echo "HOSTNAME=$(hostname)"
        echo "UPTIME=$(uptime)"
        echo "BACKUP_BY=$(whoami)"
    } > "$backup_file"
    
    echo "✅ Backup created: $backup_file"
    log_operation "INFO" "Date/time settings backed up: $backup_file"
}

# Main date/time management function
main() {
    local action="${1:-help}"
    
    case "$action" in
        "status"|"current")
            local format="${2:-all}"
            get_current_datetime "$format"
            ;;
        "set")
            local datetime_input="$2"
            local format_type="${3:-roundfleet}"
            local policy="${4:-business_hours}"
            local force="$5"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage: $0 set <datetime> [format] [policy] [force]"
                echo "Example: $0 set 120614302023.00 roundfleet business_hours"
                return 1
            fi
            
            set_enterprise_datetime "$datetime_input" "$format_type" "$policy" "$force"
            ;;
        "validate")
            local datetime_input="$2"
            local format_type="${3:-roundfleet}"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage: $0 validate <datetime> [format]"
                return 1
            fi
            
            validate_datetime_format "$datetime_input" "$format_type"
            ;;
        "convert")
            local datetime_input="$2"
            local from_format="$3"
            local to_format="$4"
            
            if [[ -z "$datetime_input" || -z "$from_format" || -z "$to_format" ]]; then
                echo "Usage: $0 convert <datetime> <from_format> <to_format>"
                echo "Available formats: roundfleet, iso8601, unix, readable"
                return 1
            fi
            
            convert_datetime_format "$datetime_input" "$from_format" "$to_format"
            ;;
        "schedule")
            local operation="$2"
            local target_datetime="$3"
            local schedule_time="$4"
            local policy="${5:-business_hours}"
            
            if [[ -z "$operation" || -z "$target_datetime" || -z "$schedule_time" ]]; then
                echo "Usage: $0 schedule <operation> <target_datetime> <schedule_time> [policy]"
                echo "Operations: set_datetime, sync_time, backup_datetime"
                return 1
            fi
            
            schedule_datetime_operation "$operation" "$target_datetime" "$schedule_time" "$policy"
            ;;
        "monitor")
            local check_type="${2:-basic}"
            
            monitor_datetime_integrity "$check_type"
            ;;
        "backup")
            local backup_type="${2:-full}"
            
            backup_datetime_settings "$backup_type"
            ;;
        "report")
            local report_type="${2:-summary}"
            
            generate_datetime_report "$report_type"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Enterprise Date and Time Management"
            echo ""
            echo "Usage: $0 <action> [options]"
            echo ""
            echo "Actions:"
            echo "  status [format]                         - Show current date/time information"
            echo "  set <datetime> [format] [policy] [force] - Set date/time with validation"
            echo "  validate <datetime> [format]            - Validate date/time format"
            echo "  convert <datetime> <from> <to>          - Convert between formats"
            echo "  schedule <op> <datetime> <time> [policy] - Schedule date/time operations"
            echo "  monitor [type]                          - Monitor date/time integrity"
            echo "  backup [type]                           - Backup date/time settings"
            echo "  report [type]                           - Generate date/time reports"
            echo "  help                                    - Show this help message"
            echo ""
            echo "Date/Time Formats:"
            for format in "${!DATE_FORMATS[@]}"; do
                echo "  $format: ${DATE_FORMATS[$format]}"
            done
            echo ""
            echo "Scheduling Policies:"
            for policy in "${!SCHEDULING_POLICIES[@]}"; do
                echo "  $policy: ${SCHEDULING_POLICIES[$policy]}"
            done
            echo ""
            echo "Monitor Types:"
            echo "  basic       - Basic integrity checks"
            echo "  comprehensive - Extended monitoring and validation"
            echo ""
            echo "Report Types:"
            echo "  summary     - Date/time overview (default)"
            echo "  compliance  - Compliance assessment"
            echo "  audit       - Complete audit trail"
            echo ""
            echo "Examples:"
            echo "  $0 set 120614302023.00                 - Set date/time in Roundfleet format"
            echo "  $0 set '2023-12-06T14:30:00' iso8601   - Set using ISO 8601 format"
            echo "  $0 convert 120614302023.00 roundfleet iso8601 - Convert formats"
            echo "  $0 schedule set_datetime 010108002024.00 '09:00 tomorrow' - Schedule operation"
            echo "  $0 monitor comprehensive               - Full integrity check"
            echo ""
            echo "Features:"
            echo "  • Enterprise-grade date/time management"
            echo "  • Multiple format support and conversion"
            echo "  • Business hours and policy enforcement"
            echo "  • Comprehensive validation and safety checks"
            echo "  • Audit logging and compliance tracking"
            echo "  • Scheduled operations and automation"
            echo "  • Real-time monitoring and integrity checks"
            ;;
    esac
}

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

Quick Reference Commands

Basic Date/Time Operations

# Check current date/time status
./datetime_manager.sh status

# Set date/time using Roundfleet format (Dec 6, 2023 2:30 PM)
./datetime_manager.sh set 120614302023.00

# Set using ISO 8601 format
./datetime_manager.sh set "2023-12-06T14:30:00" iso8601

# Validate date/time format before setting
./datetime_manager.sh validate 120614302023.00 roundfleet

Format Conversion

# Convert Roundfleet to ISO 8601
./datetime_manager.sh convert 120614302023.00 roundfleet iso8601

# Convert ISO 8601 to readable format
./datetime_manager.sh convert "2023-12-06T14:30:00" iso8601 readable

# Convert to Unix timestamp
./datetime_manager.sh convert 120614302023.00 roundfleet unix

Enterprise Operations

# Set with business hours policy enforcement
./datetime_manager.sh set 120614302023.00 roundfleet business_hours

# Force set outside business hours
./datetime_manager.sh set 120614302023.00 roundfleet business_hours true

# Schedule future date/time operation
./datetime_manager.sh schedule set_datetime 010108002024.00 "09:00 tomorrow"

Monitoring and Compliance

# Basic integrity monitoring
./datetime_manager.sh monitor basic

# Comprehensive monitoring
./datetime_manager.sh monitor comprehensive

# Generate compliance report
./datetime_manager.sh report compliance

# Backup current settings
./datetime_manager.sh backup full

Integration Examples

JAMF Pro Integration

#!/bin/bash

# JAMF Pro script for date/time management
# Parameters: $4 = target_datetime, $5 = format, $6 = policy, $7 = force

TARGET_DATETIME="$4"
FORMAT="${5:-roundfleet}"
POLICY="${6:-business_hours}"
FORCE="$7"

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

# Set date/time with enterprise controls
if [[ -n "$TARGET_DATETIME" ]]; then
    /usr/local/bin/roundfleet_datetime_manager.sh set \
        "$TARGET_DATETIME" "$FORMAT" "$POLICY" "$FORCE"
    
    # Report status back to JAMF
    if [[ $? -eq 0 ]]; then
        echo "Date/time set successfully: $TARGET_DATETIME"
        exit 0
    else
        echo "Date/time setting failed: $TARGET_DATETIME"
        exit 1
    fi
else
    echo "No target date/time provided"
    exit 1
fi

Automated Compliance Monitoring

#!/bin/bash

# Continuous date/time compliance monitoring
monitor_datetime_compliance() {
    local monitoring_interval=3600  # 1 hour
    local compliance_standard="SOX"
    
    while true; do
        # Run integrity monitoring
        if /usr/local/bin/roundfleet_datetime_manager.sh monitor comprehensive &>/dev/null; then
            echo "$(date): Date/time compliance check passed"
        else
            echo "$(date): Date/time compliance issues detected"
            
            # Generate compliance report
            /usr/local/bin/roundfleet_datetime_manager.sh report compliance
            
            # Send alert
            send_compliance_alert "Date/time integrity issues" "$compliance_standard"
        fi
        
        sleep "$monitoring_interval"
    done
}

Advanced Features

Scheduled Operations

# Advanced scheduling with business logic
schedule_maintenance_datetime() {
    local target_datetime="$1"
    local maintenance_window="$2"
    
    echo "=== Maintenance Window Date/Time Setting ==="
    echo "Target: $target_datetime"
    echo "Window: $maintenance_window"
    
    # Schedule for next maintenance window
    /usr/local/bin/roundfleet_datetime_manager.sh schedule \
        set_datetime "$target_datetime" "$maintenance_window" maintenance_window
}

Compliance Automation

# Automated compliance validation
validate_compliance_requirements() {
    local standard="$1"
    
    echo "=== Compliance Validation ==="
    echo "Standard: $standard"
    
    case "$standard" in
        "SOX")
            # Sarbanes-Oxley requires accurate timestamps
            check_timestamp_accuracy_strict
            verify_audit_trail_completeness
            ;;
        "HIPAA")
            # HIPAA requires time integrity for medical records
            check_medical_timestamp_integrity
            verify_time_source_reliability
            ;;
        "PCI_DSS")
            # PCI DSS requires accurate transaction timestamps
            check_payment_timestamp_accuracy
            verify_time_sync_security
            ;;
    esac
}

Best Practices

  1. Validate all date/time inputs before applying changes
  2. Use business hours policies to prevent unauthorized changes
  3. Implement backup and restore for critical time changes
  4. Monitor time drift continuously with automated alerting
  5. Maintain comprehensive audit logs for compliance
  6. Test format conversions before production deployment
  7. Coordinate with network teams for time synchronization
  8. Document all scheduled operations for operational awareness

This enterprise date and time management system provides comprehensive date/time control with validation, scheduling, compliance tracking, and enterprise-grade automation capabilities for effective Roundfleet time management.

Configure Trackpad Settings on macOS

Managing trackpad settings across your Roundfleet ensures consistent user experience and productivity. This tutorial covers common trackpad configurations using shell scripts for enterprise deployment.

Understanding Trackpad Settings

The trackpad settings are stored in the com.apple.AppleMultitouchTrackpad preference domain and require user context for proper application.

Basic User Context Function

All trackpad scripts require proper user context:

#!/bin/bash

# Get current logged-in user
get_current_user() {
    /bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'
}

# Execute command in user context
execute_as_user() {
    local user="$1"
    local command="$2"
    su -l "$user" -c "$command"
}

Tracking Speed Configuration

Set Tracking Speed

#!/bin/bash

loggedInUser=$(get_current_user)

# Set tracking speed (0.0 to 3.0)
# 0.0 = Slow, 1.5 = Medium, 3.0 = Fast
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad TrackingSpeed -float 1.5"

launchctl bootout user/$(id -u $loggedInUser)

Click Configuration

Set Click Pressure

#!/bin/bash

loggedInUser=$(get_current_user)

# Click options: 0 = Light, 1 = Medium, 2 = Firm
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad FirstClickThreshold -int 1"

launchctl bootout user/$(id -u $loggedInUser)

Enable Silent Clicking

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad ActuationStrength -int 0"

launchctl bootout user/$(id -u $loggedInUser)

Tap to Click Settings

Enable Tap to Click

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true"

launchctl bootout user/$(id -u $loggedInUser)

Disable Tap to Click

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad Clicking -bool false"

launchctl bootout user/$(id -u $loggedInUser)

Secondary Click (Right-Click)

Enable Two-Finger Secondary Click

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad TrackpadRightClick -bool true"

launchctl bootout user/$(id -u $loggedInUser)

Natural Scrolling

Enable Natural Scrolling

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad TrackpadScroll -bool true"

launchctl bootout user/$(id -u $loggedInUser)

Disable Natural Scrolling

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad TrackpadScroll -bool false"

launchctl bootout user/$(id -u $loggedInUser)

Look Up Feature

Disable Look Up (Three-Finger Tap)

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad ForceSuppressed -bool true"

launchctl bootout user/$(id -u $loggedInUser)

Enable Look Up

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad ForceSuppressed -bool false"

launchctl bootout user/$(id -u $loggedInUser)

Drag Lock Configuration

Enable Drag Lock

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad Dragging -bool true"
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad DragLock -bool true"

launchctl bootout user/$(id -u $loggedInUser)

Disable Drag Lock

#!/bin/bash

loggedInUser=$(get_current_user)

execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad Dragging -bool false"
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad DragLock -bool false"

launchctl bootout user/$(id -u $loggedInUser)

Enterprise Configuration Script

Complete trackpad configuration for enterprise deployment:

#!/bin/bash

# Trackpad Configuration Script for Roundfleet
# Compatible with macOS 10.14+

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

# Get current user
get_current_user() {
    /bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'
}

# Execute command in user context
execute_as_user() {
    local user="$1"
    local command="$2"
    su -l "$user" -c "$command"
}

# Main configuration function
configure_trackpad() {
    local current_user
    current_user=$(get_current_user)
    
    log_message "Starting trackpad configuration for user: $current_user"
    
    # Set tracking speed to medium
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackingSpeed -float 1.5"; then
        log_message "✓ Tracking speed set to medium"
    else
        log_message "✗ Failed to set tracking speed"
    fi
    
    # Enable tap to click
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true"; then
        log_message "✓ Tap to click enabled"
    else
        log_message "✗ Failed to enable tap to click"
    fi
    
    # Enable two-finger secondary click
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackpadRightClick -bool true"; then
        log_message "✓ Two-finger secondary click enabled"
    else
        log_message "✗ Failed to enable secondary click"
    fi
    
    # Enable natural scrolling
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackpadScroll -bool true"; then
        log_message "✓ Natural scrolling enabled"
    else
        log_message "✗ Failed to enable natural scrolling"
    fi
    
    # Set click pressure to medium
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad FirstClickThreshold -int 1"; then
        log_message "✓ Click pressure set to medium"
    else
        log_message "✗ Failed to set click pressure"
    fi
    
    # Restart user session for changes to take effect
    if launchctl bootout user/$(id -u $current_user) 2>/dev/null; then
        log_message "✓ User session restarted"
    else
        log_message "! User session restart attempted"
    fi
    
    log_message "Trackpad configuration completed"
    return 0
}

# Verification function
verify_configuration() {
    local current_user
    current_user=$(get_current_user)
    
    log_message "Verifying trackpad configuration:"
    
    local tracking_speed
    tracking_speed=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad TrackingSpeed 2>/dev/null" || echo "not set")
    log_message "  Tracking Speed: $tracking_speed"
    
    local tap_click
    tap_click=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad Clicking 2>/dev/null" || echo "not set")
    log_message "  Tap to Click: $tap_click"
    
    local right_click
    right_click=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad TrackpadRightClick 2>/dev/null" || echo "not set")
    log_message "  Secondary Click: $right_click"
}

# Execute main function
if configure_trackpad; then
    verify_configuration
    log_message "Script executed successfully"
    exit 0
else
    log_message "Script execution failed"
    exit 1
fi

Verification Script

Check current trackpad settings:

#!/bin/bash

current_user=$(get_current_user)

echo "=== Trackpad Settings Status ==="
echo "Tracking Speed: $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackingSpeed 2>/dev/null" || echo 'Not configured')"
echo "Tap to Click: $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad Clicking 2>/dev/null" || echo 'Not configured')"
echo "Secondary Click: $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackpadRightClick 2>/dev/null" || echo 'Not configured')"
echo "Natural Scrolling: $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackpadScroll 2>/dev/null" || echo 'Not configured')"
echo "Drag Lock: $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad DragLock 2>/dev/null" || echo 'Not configured')"

Troubleshooting

IssueSolution
Settings don't applyEnsure script runs with proper user context
Changes revertUse launchctl bootout to restart user session
Permission deniedRun script with admin privileges
Settings not visibleRestart System Preferences app

Reference Values

Tracking Speed

  • 0.0 - Slow
  • 1.5 - Medium (recommended)
  • 3.0 - Fast

Click Pressure

  • 0 - Light click
  • 1 - Medium click (recommended)
  • 2 - Firm click

Important Notes

  • All trackpad settings require user session restart to take effect
  • Use launchctl bootout user/$(id -u $user) to restart the user session
  • Test settings on a small group before enterprise-wide deployment
  • Users can manually override these settings in System Preferences

Code Signature Analysis and Security on macOS

Analyze and manage application code signatures on your Roundfleet devices to enhance security, verify application authenticity, and implement enterprise signing policies. This tutorial covers code requirement extraction, signature verification, and comprehensive security analysis.

Understanding macOS Code Signatures

Code signatures on macOS provide cryptographic verification that applications haven't been tampered with and come from trusted sources. Key components include:

  • Code Requirements - Constraints that code must satisfy to be considered valid
  • Bundle Identifiers - Unique identifiers for applications
  • Developer Certificates - Digital certificates used to sign applications
  • Entitlements - Permissions and capabilities granted to applications

Enterprise Security Importance

Code signature analysis is crucial for enterprise security:

  • Application Authenticity - Verify applications come from trusted developers
  • Tampering Detection - Identify modified or compromised applications
  • Privacy Policy Enforcement - Control access to protected user data
  • Compliance Requirements - Meet security standards for regulated industries
  • Malware Prevention - Block unauthorized or suspicious applications

Basic Code Signature Analysis

Extract Code Requirement

#!/bin/bash

# Basic code requirement extraction
APP_PATH="/System/Applications/Time Machine.app"

echo "Extracting code requirement for: $APP_PATH"
codesign -dr - "$APP_PATH"

Extract Code Requirement with Error Handling

#!/bin/bash

# Enhanced code requirement extraction with validation
extract_code_requirement() {
    local app_path="$1"
    
    # Validate input
    if [[ -z "$app_path" ]]; then
        echo "Error: No application path provided"
        echo "Usage: extract_code_requirement <app_path>"
        return 1
    fi
    
    # Check if application exists
    if [[ ! -e "$app_path" ]]; then
        echo "Error: Application not found at path: $app_path"
        return 1
    fi
    
    echo "=== Code Requirement Analysis ==="
    echo "Application: $app_path"
    echo ""
    
    # Extract code requirement
    local code_req
    code_req=$(codesign -dr - "$app_path" 2>&1)
    
    if [[ $? -eq 0 ]]; then
        echo "Code Requirement:"
        echo "$code_req"
        
        # Extract just the designated requirement
        local designated_req
        designated_req=$(echo "$code_req" | grep "designated =>" | sed 's/designated => //')
        
        if [[ -n "$designated_req" ]]; then
            echo ""
            echo "Designated Requirement:"
            echo "$designated_req"
        fi
    else
        echo "Error extracting code requirement:"
        echo "$code_req"
        return 1
    fi
}

# Usage examples
extract_code_requirement "/System/Applications/Safari.app"
extract_code_requirement "/Applications/Microsoft Word.app"

Comprehensive Application Analysis

#!/bin/bash

# Complete application signature analysis
analyze_application_signature() {
    local app_path="$1"
    local detailed="${2:-false}"
    
    if [[ ! -e "$app_path" ]]; then
        echo "Error: Application not found: $app_path"
        return 1
    fi
    
    echo "=== Complete Application Signature Analysis ==="
    echo "Application: $app_path"
    echo "Analysis Date: $(date)"
    echo ""
    
    # Basic information
    echo "--- Basic Information ---"
    if [[ -d "$app_path" ]]; then
        local bundle_id
        bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Unknown")
        echo "Bundle ID: $bundle_id"
        
        local app_version
        app_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Unknown")
        echo "Version: $app_version"
    fi
    
    # Code signature verification
    echo ""
    echo "--- Code Signature Verification ---"
    if codesign -v "$app_path" 2>/dev/null; then
        echo "✓ Code signature is valid"
    else
        echo "⚠️ Code signature verification failed"
    fi
    
    # Detailed signature information
    echo ""
    echo "--- Signature Details ---"
    codesign -dv "$app_path" 2>&1
    
    # Code requirements
    echo ""
    echo "--- Code Requirements ---"
    codesign -dr - "$app_path" 2>&1
    
    # Entitlements (if detailed analysis requested)
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "--- Entitlements ---"
        codesign -d --entitlements - "$app_path" 2>/dev/null || echo "No entitlements found"
    fi
    
    echo ""
    echo "=== Analysis Complete ==="
}

# Usage
analyze_application_signature "/Applications/Safari.app" "true"

Enterprise Code Signature Management

Batch Application Analysis

#!/bin/bash

# Analyze multiple applications for enterprise security review
batch_analyze_applications() {
    local scan_path="${1:-/Applications}"
    local output_format="${2:-table}"
    local include_system="${3:-false}"
    
    echo "=== Batch Application Signature Analysis ==="
    echo "Scan Path: $scan_path"
    echo "Include System Apps: $include_system"
    echo "Output Format: $output_format"
    echo ""
    
    local app_count=0
    local valid_count=0
    local invalid_count=0
    local results=()
    
    # Find all applications
    local find_paths=("$scan_path")
    if [[ "$include_system" == "true" ]]; then
        find_paths+=("/System/Applications" "/System/Library/CoreServices")
    fi
    
    for search_path in "${find_paths[@]}"; do
        if [[ -d "$search_path" ]]; then
            while IFS= read -r -d '' app_path; do
                ((app_count++))
                
                local app_name=$(basename "$app_path" .app)
                local bundle_id="Unknown"
                local signature_status="Invalid"
                local developer="Unknown"
                local code_req="Unknown"
                
                # Extract bundle ID
                if [[ -f "$app_path/Contents/Info.plist" ]]; then
                    bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Unknown")
                fi
                
                # Check signature validity
                if codesign -v "$app_path" 2>/dev/null; then
                    signature_status="Valid"
                    ((valid_count++))
                    
                    # Extract developer information
                    local sig_info
                    sig_info=$(codesign -dv "$app_path" 2>&1)
                    developer=$(echo "$sig_info" | grep "Authority=" | head -1 | sed 's/Authority=//' | tr -d '\n')
                    
                    # Extract code requirement
                    code_req=$(codesign -dr - "$app_path" 2>/dev/null | grep "designated =>" | sed 's/designated => //')
                else
                    ((invalid_count++))
                fi
                
                # Store results
                results+=("$app_name|$bundle_id|$signature_status|$developer|$code_req")
                
                # Progress indicator
                if (( app_count % 10 == 0 )); then
                    echo "Analyzed $app_count applications..."
                fi
                
            done < <(find "$search_path" -name "*.app" -type d -print0 2>/dev/null)
        fi
    done
    
    echo ""
    echo "=== Analysis Summary ==="
    echo "Total Applications: $app_count"
    echo "Valid Signatures: $valid_count"
    echo "Invalid Signatures: $invalid_count"
    echo ""
    
    # Output results in requested format
    case "$output_format" in
        "table")
            printf "%-30s %-40s %-10s %-50s\n" "Application" "Bundle ID" "Signature" "Developer"
            printf "%-30s %-40s %-10s %-50s\n" "----------" "---------" "---------" "---------"
            
            for result in "${results[@]}"; do
                IFS='|' read -r app_name bundle_id sig_status developer code_req <<< "$result"
                printf "%-30s %-40s %-10s %-50s\n" \
                    "${app_name:0:29}" \
                    "${bundle_id:0:39}" \
                    "$sig_status" \
                    "${developer:0:49}"
            done
            ;;
        "csv")
            echo "Application,Bundle ID,Signature Status,Developer,Code Requirement"
            for result in "${results[@]}"; do
                echo "$result" | tr '|' ','
            done
            ;;
        "json")
            echo "{"
            echo "  \"analysis_summary\": {"
            echo "    \"total_applications\": $app_count,"
            echo "    \"valid_signatures\": $valid_count,"
            echo "    \"invalid_signatures\": $invalid_count,"
            echo "    \"scan_date\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\""
            echo "  },"
            echo "  \"applications\": ["
            
            local first=true
            for result in "${results[@]}"; do
                IFS='|' read -r app_name bundle_id sig_status developer code_req <<< "$result"
                
                if [[ "$first" == "true" ]]; then
                    first=false
                else
                    echo ","
                fi
                
                echo -n "    {"
                echo -n "\"name\": \"$app_name\", "
                echo -n "\"bundle_id\": \"$bundle_id\", "
                echo -n "\"signature_valid\": $([ "$sig_status" == "Valid" ] && echo "true" || echo "false"), "
                echo -n "\"developer\": \"$developer\", "
                echo -n "\"code_requirement\": \"$code_req\""
                echo -n "}"
            done
            
            echo ""
            echo "  ]"
            echo "}"
            ;;
    esac
}

# Usage examples
batch_analyze_applications "/Applications" "table" "false"
batch_analyze_applications "/Applications" "json" "true" > /tmp/app_analysis.json

Security Policy Enforcement

#!/bin/bash

# Enforce enterprise code signing policies
enforce_code_signing_policy() {
    local policy_name="$1"
    local action="${2:-report}"
    local target_path="${3:-/Applications}"
    
    echo "=== Enforcing Code Signing Policy: $policy_name ==="
    echo "Action: $action"
    echo "Target Path: $target_path"
    echo ""
    
    local violations=()
    local compliant_apps=()
    
    case "$policy_name" in
        "enterprise_strict")
            echo "Policy: Enterprise Strict - Only signed applications from trusted developers"
            
            # Define trusted developers
            local trusted_developers=(
                "Apple Inc."
                "Microsoft Corporation"
                "Adobe Inc."
                "Google LLC"
                "Zoom Video Communications, Inc."
            )
            
            check_enterprise_strict_policy "$target_path" trusted_developers violations compliant_apps
            ;;
        "apple_signed_only")
            echo "Policy: Apple Signed Only - Only Apple-signed applications allowed"
            check_apple_signed_policy "$target_path" violations compliant_apps
            ;;
        "no_unsigned")
            echo "Policy: No Unsigned - All applications must be signed"
            check_no_unsigned_policy "$target_path" violations compliant_apps
            ;;
        "developer_id_required")
            echo "Policy: Developer ID Required - All apps must have valid Developer ID"
            check_developer_id_policy "$target_path" violations compliant_apps
            ;;
        *)
            echo "Error: Unknown policy '$policy_name'"
            echo "Available policies: enterprise_strict, apple_signed_only, no_unsigned, developer_id_required"
            return 1
            ;;
    esac
    
    # Report results
    echo ""
    echo "=== Policy Enforcement Results ==="
    echo "Compliant Applications: ${#compliant_apps[@]}"
    echo "Policy Violations: ${#violations[@]}"
    
    if [[ ${#violations[@]} -gt 0 ]]; then
        echo ""
        echo "Policy Violations Found:"
        for violation in "${violations[@]}"; do
            echo "  ⚠️ $violation"
        done
    fi
    
    # Take action based on policy
    case "$action" in
        "report")
            echo ""
            echo "Action: Report Only - No changes made"
            generate_policy_report "$policy_name" violations compliant_apps
            ;;
        "quarantine")
            echo ""
            echo "Action: Quarantine - Moving violating applications"
            quarantine_violations violations
            ;;
        "remove")
            echo ""
            echo "Action: Remove - Deleting violating applications"
            remove_violations violations
            ;;
        *)
            echo "Error: Unknown action '$action'"
            ;;
    esac
}

# Check enterprise strict policy
check_enterprise_strict_policy() {
    local target_path="$1"
    local -n trusted_devs=$2
    local -n violations_ref=$3
    local -n compliant_ref=$4
    
    while IFS= read -r -d '' app_path; do
        local app_name=$(basename "$app_path")
        
        if codesign -v "$app_path" 2>/dev/null; then
            local developer
            developer=$(codesign -dv "$app_path" 2>&1 | grep "Authority=" | head -1 | sed 's/Authority=//')
            
            local is_trusted=false
            for trusted_dev in "${trusted_devs[@]}"; do
                if [[ "$developer" == *"$trusted_dev"* ]]; then
                    is_trusted=true
                    break
                fi
            done
            
            if [[ "$is_trusted" == "true" ]]; then
                compliant_ref+=("$app_name")
            else
                violations_ref+=("$app_name (Developer: $developer)")
            fi
        else
            violations_ref+=("$app_name (Unsigned)")
        fi
    done < <(find "$target_path" -name "*.app" -type d -print0 2>/dev/null)
}

# Check Apple-signed only policy
check_apple_signed_policy() {
    local target_path="$1"
    local -n violations_ref=$2
    local -n compliant_ref=$3
    
    while IFS= read -r -d '' app_path; do
        local app_name=$(basename "$app_path")
        
        if codesign -v "$app_path" 2>/dev/null; then
            local developer
            developer=$(codesign -dv "$app_path" 2>&1 | grep "Authority=" | head -1 | sed 's/Authority=//')
            
            if [[ "$developer" == *"Apple"* ]]; then
                compliant_ref+=("$app_name")
            else
                violations_ref+=("$app_name (Non-Apple Developer: $developer)")
            fi
        else
            violations_ref+=("$app_name (Unsigned)")
        fi
    done < <(find "$target_path" -name "*.app" -type d -print0 2>/dev/null)
}

# Generate policy compliance report
generate_policy_report() {
    local policy_name="$1"
    local -n violations_ref=$2
    local -n compliant_ref=$3
    
    local report_file="/tmp/code_signing_policy_report_$(date +%Y%m%d_%H%M%S).json"
    
    cat > "$report_file" << EOF
{
    "code_signing_policy_report": {
        "policy_name": "$policy_name",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "summary": {
            "total_applications": $((${#violations_ref[@]} + ${#compliant_ref[@]})),
            "compliant_applications": ${#compliant_ref[@]},
            "policy_violations": ${#violations_ref[@]},
            "compliance_percentage": $(( ${#compliant_ref[@]} * 100 / (${#violations_ref[@]} + ${#compliant_ref[@]}) ))
        },
        "violations": [
EOF
    
    local first=true
    for violation in "${violations_ref[@]}"; do
        if [[ "$first" == "true" ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        echo -n "            \"$violation\"" >> "$report_file"
    done
    
    cat >> "$report_file" << EOF

        ],
        "compliant_applications": [
EOF
    
    first=true
    for compliant in "${compliant_ref[@]}"; do
        if [[ "$first" == "true" ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        echo -n "            \"$compliant\"" >> "$report_file"
    done
    
    cat >> "$report_file" << EOF

        ]
    }
}
EOF
    
    echo "Policy report generated: $report_file"
}

# Usage
enforce_code_signing_policy "enterprise_strict" "report" "/Applications"

Enterprise Code Signature Management System

#!/bin/bash

# Roundfleet Code Signature Management Tool
# Comprehensive code signature analysis and security policy enforcement

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_codesigning.log"
REPORT_DIR="/etc/roundfleet/reports/codesigning"
CONFIG_DIR="/etc/roundfleet/codesigning"
POLICY_DIR="/etc/roundfleet/policies/codesigning"
QUARANTINE_DIR="/var/quarantine/applications"

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

# Code signing policy templates
declare -A SIGNING_POLICIES=(
    ["enterprise_standard"]="signed_required,developer_id_preferred,apple_signed_trusted,third_party_review"
    ["enterprise_strict"]="apple_signed_only,developer_id_required,no_unsigned,enterprise_review"
    ["development"]="signed_preferred,developer_id_optional,self_signed_allowed,minimal_restrictions"
    ["kiosk_lockdown"]="apple_signed_only,no_third_party,system_apps_only,maximum_security"
    ["healthcare"]="apple_signed_required,enterprise_approved_only,no_unsigned,hipaa_compliant"
    ["financial"]="apple_signed_required,enterprise_certified_only,strict_validation,sox_compliant"
    ["education"]="signed_required,educational_approved,apple_preferred,moderate_security"
    ["government"]="apple_signed_only,government_approved,no_unsigned,maximum_security"
    ["retail"]="signed_required,pos_approved,apple_preferred,moderate_security"
    ["manufacturing"]="signed_required,industrial_approved,apple_preferred,operational_security"
)

# Trusted developer registry
declare -A TRUSTED_DEVELOPERS=(
    ["apple"]="Apple Inc.,Software Signing,Apple Mac OS Application Signing"
    ["microsoft"]="Microsoft Corporation,Microsoft Corporation"
    ["adobe"]="Adobe Inc.,Adobe Systems Incorporated"
    ["google"]="Google LLC,Google Inc."
    ["zoom"]="Zoom Video Communications, Inc."
    ["slack"]="Slack Technologies, Inc."
    ["dropbox"]="Dropbox, Inc."
    ["1password"]="AgileBits Inc."
    ["firefox"]="Mozilla Corporation"
    ["chrome"]="Google LLC"
)

# Security classification levels
declare -A SECURITY_LEVELS=(
    ["maximum"]="apple_signed_only,no_exceptions,immediate_quarantine"
    ["high"]="signed_required,trusted_developers_only,review_required"
    ["medium"]="signed_preferred,warnings_enabled,monitoring_active"
    ["low"]="unsigned_allowed,notification_only,basic_monitoring"
)

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

# Advanced code signature analysis
analyze_code_signature() {
    local app_path="$1"
    local output_format="${2:-detailed}"
    local security_check="${3:-true}"
    
    log_action "Analyzing code signature for: $app_path"
    
    if [[ ! -e "$app_path" ]]; then
        log_action "ERROR: Application not found: $app_path"
        return 1
    fi
    
    local analysis_data=()
    local app_name=$(basename "$app_path" .app)
    
    echo "=== Advanced Code Signature Analysis ==="
    echo "Application: $app_name"
    echo "Path: $app_path"
    echo "Analysis Date: $(date)"
    echo ""
    
    # Basic application information
    extract_app_metadata "$app_path" analysis_data
    
    # Code signature verification
    verify_code_signature "$app_path" analysis_data
    
    # Extract code requirements
    extract_code_requirements "$app_path" analysis_data
    
    # Security analysis
    if [[ "$security_check" == "true" ]]; then
        perform_security_analysis "$app_path" analysis_data
    fi
    
    # Generate output in requested format
    case "$output_format" in
        "detailed")
            display_detailed_analysis analysis_data
            ;;
        "summary")
            display_summary_analysis analysis_data
            ;;
        "json")
            generate_json_analysis "$app_path" analysis_data
            ;;
        "csv")
            generate_csv_analysis "$app_path" analysis_data
            ;;
    esac
    
    log_action "Code signature analysis completed for: $app_path"
}

# Extract application metadata
extract_app_metadata() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo "--- Application Metadata ---"
    
    if [[ -f "$app_path/Contents/Info.plist" ]]; then
        local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Unknown")
        local version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Unknown")
        local build=$(defaults read "$app_path/Contents/Info.plist" CFBundleVersion 2>/dev/null || echo "Unknown")
        local min_os=$(defaults read "$app_path/Contents/Info.plist" LSMinimumSystemVersion 2>/dev/null || echo "Unknown")
        
        echo "Bundle ID: $bundle_id"
        echo "Version: $version"
        echo "Build: $build"
        echo "Minimum OS: $min_os"
        
        data_ref+=("bundle_id:$bundle_id")
        data_ref+=("version:$version")
        data_ref+=("build:$build")
        data_ref+=("min_os:$min_os")
    else
        echo "No Info.plist found"
        data_ref+=("bundle_id:Unknown")
    fi
    
    # File size and modification date
    local file_size=$(du -sh "$app_path" | cut -f1)
    local mod_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path")
    
    echo "Application Size: $file_size"
    echo "Last Modified: $mod_date"
    
    data_ref+=("size:$file_size")
    data_ref+=("modified:$mod_date")
}

# Verify code signature
verify_code_signature() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Code Signature Verification ---"
    
    # Basic verification
    if codesign -v "$app_path" 2>/dev/null; then
        echo "✓ Code signature is valid"
        data_ref+=("signature_valid:true")
        
        # Detailed signature information
        local sig_info=$(codesign -dv "$app_path" 2>&1)
        
        # Extract key information
        local identifier=$(echo "$sig_info" | grep "Identifier=" | sed 's/Identifier=//')
        local format=$(echo "$sig_info" | grep "Format=" | sed 's/Format=//')
        local cdhash=$(echo "$sig_info" | grep "CDHash=" | sed 's/CDHash=//')
        local team_id=$(echo "$sig_info" | grep "TeamIdentifier=" | sed 's/TeamIdentifier=//')
        
        echo "Identifier: $identifier"
        echo "Format: $format"
        echo "CDHash: $cdhash"
        echo "Team ID: $team_id"
        
        data_ref+=("identifier:$identifier")
        data_ref+=("format:$format")
        data_ref+=("cdhash:$cdhash")
        data_ref+=("team_id:$team_id")
        
        # Extract certificate chain
        local authorities=$(echo "$sig_info" | grep "Authority=" | sed 's/Authority=//')
        echo "Certificate Chain:"
        while IFS= read -r authority; do
            echo "  - $authority"
        done <<< "$authorities"
        
        data_ref+=("authorities:$authorities")
        
    else
        echo "⚠️ Code signature verification FAILED"
        data_ref+=("signature_valid:false")
        
        local error=$(codesign -v "$app_path" 2>&1)
        echo "Error: $error"
        data_ref+=("signature_error:$error")
    fi
}

# Extract code requirements
extract_code_requirements() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Code Requirements ---"
    
    local req_output=$(codesign -dr - "$app_path" 2>&1)
    
    if [[ $? -eq 0 ]]; then
        echo "$req_output"
        
        # Extract designated requirement
        local designated_req=$(echo "$req_output" | grep "designated =>" | sed 's/designated => //')
        if [[ -n "$designated_req" ]]; then
            echo ""
            echo "Designated Requirement:"
            echo "$designated_req"
            data_ref+=("designated_requirement:$designated_req")
        fi
        
        data_ref+=("requirements_extracted:true")
    else
        echo "Failed to extract code requirements"
        echo "$req_output"
        data_ref+=("requirements_extracted:false")
    fi
}

# Perform security analysis
perform_security_analysis() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Security Analysis ---"
    
    local security_score=100
    local security_issues=()
    
    # Check if application is signed
    if ! codesign -v "$app_path" 2>/dev/null; then
        security_score=$((security_score - 50))
        security_issues+=("Application is not signed")
    fi
    
    # Check for hardened runtime
    local flags=$(codesign -dv "$app_path" 2>&1 | grep "CodeDirectory" | grep "runtime")
    if [[ -n "$flags" ]]; then
        echo "✓ Hardened runtime enabled"
        data_ref+=("hardened_runtime:true")
    else
        echo "⚠️ Hardened runtime not enabled"
        security_score=$((security_score - 20))
        security_issues+=("Hardened runtime not enabled")
        data_ref+=("hardened_runtime:false")
    fi
    
    # Check for notarization
    if spctl -a -v "$app_path" 2>&1 | grep -q "notarized"; then
        echo "✓ Application is notarized"
        data_ref+=("notarized:true")
    else
        echo "⚠️ Application is not notarized"
        security_score=$((security_score - 15))
        security_issues+=("Application not notarized")
        data_ref+=("notarized:false")
    fi
    
    # Check for known vulnerabilities (basic check)
    check_known_vulnerabilities "$app_path" security_score security_issues
    
    echo ""
    echo "Security Score: $security_score/100"
    data_ref+=("security_score:$security_score")
    
    if [[ ${#security_issues[@]} -gt 0 ]]; then
        echo "Security Issues Found:"
        for issue in "${security_issues[@]}"; do
            echo "  ⚠️ $issue"
        done
        data_ref+=("security_issues:${security_issues[*]}")
    else
        echo "✓ No security issues found"
        data_ref+=("security_issues:none")
    fi
}

# Check for known vulnerabilities
check_known_vulnerabilities() {
    local app_path="$1"
    local -n score_ref=$2
    local -n issues_ref=$3
    
    local bundle_id
    bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Unknown")
    
    # Check against known vulnerable applications (simplified example)
    case "$bundle_id" in
        "com.adobe.flashplayer"*)
            score_ref=$((score_ref - 30))
            issues_ref+=("Flash Player has known security vulnerabilities")
            ;;
        "com.java."*)
            # Check Java version for known vulnerabilities
            local java_version
            java_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
            if [[ -n "$java_version" ]]; then
                echo "Java version detected: $java_version"
                # Add specific version checks here
            fi
            ;;
    esac
    
    # Check for applications with expired certificates
    local cert_info=$(codesign -dv "$app_path" 2>&1 | grep "Timestamp=")
    if [[ -n "$cert_info" ]]; then
        # Extract timestamp and check if certificate is old
        local timestamp=$(echo "$cert_info" | sed 's/Timestamp=//')
        echo "Certificate timestamp: $timestamp"
    fi
}

# Generate comprehensive fleet analysis
analyze_fleet_applications() {
    local scan_paths=("$@")
    local report_file="$REPORT_DIR/fleet_analysis_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Fleet-Wide Application Analysis ==="
    echo "Scanning paths: ${scan_paths[*]}"
    echo ""
    
    local total_apps=0
    local signed_apps=0
    local unsigned_apps=0
    local notarized_apps=0
    local security_issues=0
    local applications=()
    
    for scan_path in "${scan_paths[@]}"; do
        if [[ -d "$scan_path" ]]; then
            echo "Scanning: $scan_path"
            
            while IFS= read -r -d '' app_path; do
                ((total_apps++))
                
                local app_name=$(basename "$app_path" .app)
                local analysis_data=()
                
                # Quick analysis for fleet overview
                analyze_code_signature "$app_path" "summary" "true" > /dev/null
                
                # Extract key metrics
                if codesign -v "$app_path" 2>/dev/null; then
                    ((signed_apps++))
                else
                    ((unsigned_apps++))
                fi
                
                if spctl -a -v "$app_path" 2>&1 | grep -q "notarized"; then
                    ((notarized_apps++))
                fi
                
                # Add to applications array
                applications+=("$app_path")
                
                # Progress indicator
                if (( total_apps % 25 == 0 )); then
                    echo "Analyzed $total_apps applications..."
                fi
                
            done < <(find "$scan_path" -name "*.app" -type d -maxdepth 2 -print0 2>/dev/null)
        fi
    done
    
    # Generate fleet analysis report
    cat > "$report_file" << EOF
{
    "fleet_analysis": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "scan_paths": [$(printf '"%s",' "${scan_paths[@]}" | sed 's/,$//')],
        "summary": {
            "total_applications": $total_apps,
            "signed_applications": $signed_apps,
            "unsigned_applications": $unsigned_apps,
            "notarized_applications": $notarized_apps,
            "signing_compliance": $(( signed_apps * 100 / total_apps )),
            "notarization_compliance": $(( notarized_apps * 100 / total_apps ))
        },
        "analysis_date": "$(date)",
        "script_version": "$SCRIPT_VERSION"
    }
}
EOF
    
    echo ""
    echo "=== Fleet Analysis Summary ==="
    echo "Total Applications: $total_apps"
    echo "Signed Applications: $signed_apps ($(( signed_apps * 100 / total_apps ))%)"
    echo "Unsigned Applications: $unsigned_apps ($(( unsigned_apps * 100 / total_apps ))%)"
    echo "Notarized Applications: $notarized_apps ($(( notarized_apps * 100 / total_apps ))%)"
    echo ""
    echo "Fleet analysis report: $report_file"
    
    log_action "Fleet analysis completed: $total_apps applications analyzed"
}

# Main execution function
main() {
    local action="${1:-help}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Roundfleet Code Signature Management Started ==="
    log_action "Action: $action"
    
    case "$action" in
        "analyze")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 analyze <app_path> [output_format] [security_check]"
                echo "Output formats: detailed, summary, json, csv"
                exit 1
            fi
            analyze_code_signature "$param1" "${param2:-detailed}" "${param3:-true}"
            ;;
        "extract")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 extract <app_path>"
                exit 1
            fi
            extract_code_requirement "$param1"
            ;;
        "batch")
            if [[ -z "$param1" ]]; then
                param1="/Applications"
            fi
            batch_analyze_applications "$param1" "${param2:-table}" "${param3:-false}"
            ;;
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Available policies: ${!SIGNING_POLICIES[*]}"
                exit 1
            fi
            enforce_code_signing_policy "$param1" "${param2:-report}" "${param3:-/Applications}"
            ;;
        "fleet")
            local paths=("${@:2}")
            if [[ ${#paths[@]} -eq 0 ]]; then
                paths=("/Applications" "/System/Applications")
            fi
            analyze_fleet_applications "${paths[@]}"
            ;;
        "verify")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 verify <app_path>"
                exit 1
            fi
            if codesign -v "$param1" 2>/dev/null; then
                echo "✓ Code signature is valid for: $param1"
            else
                echo "⚠️ Code signature verification failed for: $param1"
                codesign -v "$param1"
            fi
            ;;
        "help")
            echo "Usage: $0 [action] [options...]"
            echo "Actions:"
            echo "  analyze <app_path> [format] [security] - Analyze application signature"
            echo "  extract <app_path> - Extract code requirement only"
            echo "  batch <scan_path> [format] [include_system] - Batch analyze applications"
            echo "  policy <policy_name> [action] [path] - Enforce signing policy"
            echo "  fleet [paths...] - Analyze fleet-wide applications"
            echo "  verify <app_path> - Quick signature verification"
            echo "  help - Show this help"
            echo ""
            echo "Output Formats: detailed, summary, json, csv, table"
            echo "Policies: ${!SIGNING_POLICIES[*]}"
            echo "Security Levels: ${!SECURITY_LEVELS[*]}"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
    
    log_action "=== Code signature management completed ==="
}

# Execute main function
main "$@"

Security Best Practices

Enterprise Certificate Management

#!/bin/bash

# Enterprise certificate validation
validate_enterprise_certificates() {
    local cert_policy="${1:-strict}"
    
    echo "=== Enterprise Certificate Validation ==="
    echo "Policy: $cert_policy"
    echo ""
    
    local expired_certs=()
    local revoked_certs=()
    local untrusted_certs=()
    
    # Check system keychain for enterprise certificates
    security find-certificate -a -p /Library/Keychains/System.keychain | \
    while IFS= read -r cert_line; do
        if [[ "$cert_line" == "-----BEGIN CERTIFICATE-----" ]]; then
            # Process certificate
            echo "Checking enterprise certificate..."
        fi
    done
    
    echo "✓ Enterprise certificate validation completed"
}

validate_enterprise_certificates "strict"

Compliance Reporting

#!/bin/bash

# Generate compliance report for regulatory requirements
generate_compliance_report() {
    local compliance_type="${1:-general}"
    local output_file="$REPORT_DIR/compliance_${compliance_type}_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Compliance Report: $compliance_type ==="
    
    local total_apps=0
    local compliant_apps=0
    local non_compliant_apps=0
    
    # Scan applications for compliance
    while IFS= read -r -d '' app_path; do
        ((total_apps++))
        
        case "$compliance_type" in
            "hipaa")
                check_hipaa_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            "sox")
                check_sox_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            "pci_dss")
                check_pci_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            *)
                check_general_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
        esac
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Generate report
    local compliance_percentage=$(( compliant_apps * 100 / total_apps ))
    
    cat > "$output_file" << EOF
{
    "compliance_report": {
        "type": "$compliance_type",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "summary": {
            "total_applications": $total_apps,
            "compliant_applications": $compliant_apps,
            "non_compliant_applications": $non_compliant_apps,
            "compliance_percentage": $compliance_percentage
        }
    }
}
EOF
    
    echo "Compliance report generated: $output_file"
    echo "Compliance rate: $compliance_percentage%"
}

generate_compliance_report "general"

Important Notes

  • Code signatures verify application authenticity and integrity
  • Code requirements specify constraints for application validation
  • Enterprise policies should balance security with operational needs
  • Regular monitoring helps detect unauthorized applications
  • Compliance requirements vary by industry and regulatory framework
  • Notarization provides additional security validation from Apple
  • Certificate management is crucial for enterprise security
  • Fleet-wide analysis enables proactive security management

Clipboard Management for macOS

Implement enterprise-grade clipboard management across your Roundfleet deployment with secure content distribution, automated text deployment, clipboard monitoring, and comprehensive policies for controlled information sharing. This tutorial provides solutions for managing clipboard operations while maintaining security and compliance standards.

Understanding macOS Clipboard Management

macOS provides several command-line tools for clipboard operations:

  • pbcopy - Copy text or data to the system clipboard
  • pbpaste - Retrieve content from the system clipboard
  • pbcopy -pboard - Work with specific pasteboard types
  • Accessibility APIs - Monitor clipboard changes programmatically
  • Security frameworks - Control clipboard access permissions

Basic Clipboard Operations

Copy Text to Clipboard

#!/bin/bash

# Basic clipboard copy operation
echo "Content to be copied to clipboard" | pbcopy

Enhanced Clipboard Copy

#!/bin/bash

# Enhanced clipboard copy with validation
CONTENT="$1"

if [[ -z "$CONTENT" ]]; then
    echo "Error: No content provided"
    exit 1
fi

# Copy content to clipboard
echo "$CONTENT" | pbcopy

if [[ $? -eq 0 ]]; then
    echo "Content copied to clipboard successfully"
else
    echo "Failed to copy content to clipboard"
    exit 1
fi

Retrieve Clipboard Content

#!/bin/bash

# Retrieve and display clipboard content
CLIPBOARD_CONTENT=$(pbpaste)

if [[ -n "$CLIPBOARD_CONTENT" ]]; then
    echo "Current clipboard content:"
    echo "$CLIPBOARD_CONTENT"
else
    echo "Clipboard is empty"
fi

Enterprise Clipboard Management System

Comprehensive Clipboard Management Tool

#!/bin/bash

# Roundfleet Enterprise Clipboard Management Tool
# Secure content distribution and clipboard monitoring

# Configuration
CONFIG_FILE="/etc/roundfleet/clipboard_policy.conf"
LOG_FILE="/var/log/roundfleet_clipboard.log"
CACHE_DIR="/Library/Roundfleet/Clipboard"
AUDIT_LOG="/var/log/roundfleet_clipboard_audit.log"

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

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

# Content Security Settings
ALLOW_SENSITIVE_CONTENT=false
ENCRYPT_CLIPBOARD_LOGS=true
SANITIZE_CONTENT=true
MAX_CONTENT_LENGTH=10240

# Access Control
RESTRICT_CLIPBOARD_ACCESS=true
ALLOWED_APPLICATIONS=("TextEdit" "Notes" "Mail" "Slack" "Microsoft Word")
BLOCKED_APPLICATIONS=("Terminal" "Script Editor")
LOG_CLIPBOARD_OPERATIONS=true

# Content Filtering
FILTER_SENSITIVE_DATA=true
BLOCK_CREDIT_CARDS=true
BLOCK_SSN=true
BLOCK_PASSWORDS=true
CONTENT_SCAN_ENABLED=true

# Distribution Settings
ENTERPRISE_CONTENT_ENABLED=true
CONTENT_TEMPLATES_DIR="/Library/Roundfleet/Templates"
SCHEDULED_CONTENT_ENABLED=false
CONTENT_EXPIRY_ENABLED=true
DEFAULT_EXPIRY_MINUTES=60

# Monitoring and Compliance
MONITOR_CLIPBOARD_CHANGES=true
AUDIT_CLIPBOARD_ACCESS=true
COMPLIANCE_ALERTS=true
SEND_USAGE_REPORTS=true
RETENTION_DAYS=90

# Security Settings
REQUIRE_ADMIN_APPROVAL=false
ENCRYPT_SENSITIVE_CONTENT=true
PREVENT_EXTERNAL_PASTE=false
CLEAR_ON_LOGOUT=true
EOF

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

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

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

# Content sanitization
sanitize_content() {
    local content="$1"
    local sanitized="$content"
    
    if [[ "$SANITIZE_CONTENT" == "true" ]]; then
        # Remove potential script injections
        sanitized=$(echo "$sanitized" | sed 's/<script[^>]*>.*<\/script>//gi')
        sanitized=$(echo "$sanitized" | sed 's/javascript:[^"]*//gi')
        sanitized=$(echo "$sanitized" | sed 's/data:[^"]*//gi')
        
        # Limit content length
        if [[ ${#sanitized} -gt $MAX_CONTENT_LENGTH ]]; then
            sanitized="${sanitized:0:$MAX_CONTENT_LENGTH}...[TRUNCATED]"
        fi
    fi
    
    echo "$sanitized"
}

# Sensitive data detection
detect_sensitive_data() {
    local content="$1"
    local violations=()
    
    if [[ "$FILTER_SENSITIVE_DATA" != "true" ]]; then
        return 0
    fi
    
    # Credit card detection
    if [[ "$BLOCK_CREDIT_CARDS" == "true" ]]; then
        if echo "$content" | grep -E '\b[0-9]{4}[[:space:]-]?[0-9]{4}[[:space:]-]?[0-9]{4}[[:space:]-]?[0-9]{4}\b' >/dev/null; then
            violations+=("Credit card number detected")
        fi
    fi
    
    # SSN detection
    if [[ "$BLOCK_SSN" == "true" ]]; then
        if echo "$content" | grep -E '\b[0-9]{3}-[0-9]{2}-[0-9]{4}\b' >/dev/null; then
            violations+=("Social Security Number detected")
        fi
    fi
    
    # Password patterns
    if [[ "$BLOCK_PASSWORDS" == "true" ]]; then
        if echo "$content" | grep -i -E '(password|pwd|passwd|pass)[[:space:]]*[:=][[:space:]]*[^[:space:]]+' >/dev/null; then
            violations+=("Password pattern detected")
        fi
    fi
    
    # API keys and tokens
    if echo "$content" | grep -E '\b[A-Za-z0-9+/]{40,}\b' >/dev/null; then
        violations+=("Potential API key or token detected")
    fi
    
    # Return violations
    if [[ ${#violations[@]} -gt 0 ]]; then
        printf '%s\n' "${violations[@]}"
        return 1
    else
        return 0
    fi
}

# Application access control
check_app_permissions() {
    local app_name="$1"
    
    if [[ "$RESTRICT_CLIPBOARD_ACCESS" != "true" ]]; then
        return 0
    fi
    
    # Get current application
    if [[ -z "$app_name" ]]; then
        app_name=$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' 2>/dev/null || echo "Unknown")
    fi
    
    # Check allowed applications
    for allowed_app in "${ALLOWED_APPLICATIONS[@]}"; do
        if [[ "$app_name" == "$allowed_app" ]]; then
            echo "✅ Application $app_name is allowed"
            return 0
        fi
    done
    
    # Check blocked applications
    for blocked_app in "${BLOCKED_APPLICATIONS[@]}"; do
        if [[ "$app_name" == "$blocked_app" ]]; then
            echo "❌ Application $app_name is blocked"
            audit_log "BLOCKED_ACCESS" "N/A" "$app_name"
            return 1
        fi
    done
    
    # Default policy for unlisted applications
    echo "⚠️  Application $app_name not in policy (defaulting to allowed)"
    return 0
}

# Copy content to clipboard with enterprise features
enterprise_clipboard_copy() {
    local content="$1"
    local source_app="${2:-System}"
    local force_copy="${3:-false}"
    
    echo "=== Enterprise Clipboard Copy Operation ==="
    
    # Validate input
    if [[ -z "$content" ]]; then
        echo "❌ No content provided"
        return 1
    fi
    
    # Check application permissions
    if ! check_app_permissions "$source_app"; then
        echo "❌ Application not authorized for clipboard access"
        return 1
    fi
    
    # Sanitize content
    local sanitized_content
    sanitized_content=$(sanitize_content "$content")
    
    # Detect sensitive data
    local violations
    if violations=$(detect_sensitive_data "$sanitized_content"); then
        if [[ "$force_copy" != "true" ]]; then
            echo "❌ Sensitive data detected:"
            echo "$violations"
            audit_log "SENSITIVE_BLOCKED" "$(echo "$content" | md5)" "$source_app"
            return 1
        else
            echo "⚠️  Sensitive data detected but force copy enabled"
            log_action "WARNING: Sensitive data copied with force flag: $violations"
        fi
    fi
    
    # Copy to clipboard
    if echo "$sanitized_content" | pbcopy; then
        echo "✅ Content copied to clipboard successfully"
        
        # Log operation
        local content_hash
        content_hash=$(echo "$sanitized_content" | md5)
        log_action "Clipboard copy successful - Hash: $content_hash - App: $source_app"
        audit_log "COPY_SUCCESS" "$content_hash" "$source_app"
        
        # Schedule content expiry if enabled
        if [[ "$CONTENT_EXPIRY_ENABLED" == "true" ]]; then
            schedule_clipboard_expiry "$DEFAULT_EXPIRY_MINUTES"
        fi
        
        return 0
    else
        echo "❌ Failed to copy content to clipboard"
        log_action "FAILED: Clipboard copy operation"
        audit_log "COPY_FAILED" "N/A" "$source_app"
        return 1
    fi
}

# Schedule clipboard content expiry
schedule_clipboard_expiry() {
    local expiry_minutes="$1"
    
    if [[ -n "$expiry_minutes" && $expiry_minutes -gt 0 ]]; then
        # Create a background job to clear clipboard after expiry
        (
            sleep $((expiry_minutes * 60))
            echo "" | pbcopy
            log_action "Clipboard content expired and cleared after $expiry_minutes minutes"
        ) &
        
        echo "🕒 Clipboard content will expire in $expiry_minutes minutes"
    fi
}

# Retrieve clipboard content with security checks
enterprise_clipboard_paste() {
    local requesting_app="${1:-System}"
    
    echo "=== Enterprise Clipboard Paste Operation ==="
    
    # Check application permissions
    if ! check_app_permissions "$requesting_app"; then
        echo "❌ Application not authorized for clipboard access"
        return 1
    fi
    
    # Get clipboard content
    local clipboard_content
    clipboard_content=$(pbpaste)
    
    if [[ -z "$clipboard_content" ]]; then
        echo "📋 Clipboard is empty"
        return 1
    fi
    
    # Log access
    local content_hash
    content_hash=$(echo "$clipboard_content" | md5)
    log_action "Clipboard access - Hash: $content_hash - App: $requesting_app"
    audit_log "PASTE_ACCESS" "$content_hash" "$requesting_app"
    
    # Return content
    echo "$clipboard_content"
    return 0
}

# Deploy enterprise content templates
deploy_enterprise_content() {
    local template_name="$1"
    local target_users="${2:-all}"
    
    echo "=== Enterprise Content Deployment ==="
    echo "Template: $template_name"
    echo "Target: $target_users"
    
    if [[ "$ENTERPRISE_CONTENT_ENABLED" != "true" ]]; then
        echo "❌ Enterprise content deployment disabled"
        return 1
    fi
    
    # Load template
    local template_file="$CONTENT_TEMPLATES_DIR/$template_name.txt"
    
    if [[ ! -f "$template_file" ]]; then
        echo "❌ Template not found: $template_file"
        return 1
    fi
    
    local template_content
    template_content=$(cat "$template_file")
    
    # Process template variables
    template_content=$(echo "$template_content" | sed "s/{{HOSTNAME}}/$(hostname)/g")
    template_content=$(echo "$template_content" | sed "s/{{USER}}/$(whoami)/g")
    template_content=$(echo "$template_content" | sed "s/{{DATE}}/$(date)/g")
    template_content=$(echo "$template_content" | sed "s/{{TIMESTAMP}}/$(date '+%Y-%m-%d %H:%M:%S')/g")
    
    # Deploy content
    if enterprise_clipboard_copy "$template_content" "Enterprise_Deployment" "true"; then
        echo "✅ Enterprise content deployed successfully"
        log_action "Enterprise content deployed: $template_name"
        return 0
    else
        echo "❌ Failed to deploy enterprise content"
        return 1
    fi
}

# Monitor clipboard changes
monitor_clipboard() {
    echo "=== Starting Clipboard Monitoring ==="
    
    if [[ "$MONITOR_CLIPBOARD_CHANGES" != "true" ]]; then
        echo "Clipboard monitoring disabled"
        return 0
    fi
    
    local previous_hash=""
    local current_hash=""
    
    echo "Monitoring clipboard changes... Press Ctrl+C to stop"
    
    while true; do
        current_hash=$(pbpaste | md5 2>/dev/null || echo "")
        
        if [[ "$current_hash" != "$previous_hash" && -n "$current_hash" ]]; then
            echo "🔄 Clipboard content changed at $(date)"
            
            # Get current app
            local current_app
            current_app=$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' 2>/dev/null || echo "Unknown")
            
            # Log change
            log_action "Clipboard change detected - Hash: $current_hash - App: $current_app"
            audit_log "CONTENT_CHANGED" "$current_hash" "$current_app"
            
            # Check for sensitive content
            local clipboard_content
            clipboard_content=$(pbpaste)
            
            if violations=$(detect_sensitive_data "$clipboard_content"); then
                echo "⚠️  Sensitive data detected in clipboard:"
                echo "$violations"
                
                if [[ "$COMPLIANCE_ALERTS" == "true" ]]; then
                    log_action "COMPLIANCE ALERT: Sensitive data in clipboard - $violations"
                fi
            fi
            
            previous_hash="$current_hash"
        fi
        
        sleep 2
    done
}

# Generate clipboard usage report
generate_clipboard_report() {
    local report_file="$CACHE_DIR/clipboard_report_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Clipboard Usage Report ==="
    
    # Analyze audit log
    local total_operations=0
    local copy_operations=0
    local paste_operations=0
    local blocked_operations=0
    local sensitive_blocks=0
    
    if [[ -f "$AUDIT_LOG" ]]; then
        total_operations=$(wc -l < "$AUDIT_LOG")
        copy_operations=$(grep -c "COPY_SUCCESS" "$AUDIT_LOG" || echo 0)
        paste_operations=$(grep -c "PASTE_ACCESS" "$AUDIT_LOG" || echo 0)
        blocked_operations=$(grep -c "BLOCKED_ACCESS" "$AUDIT_LOG" || echo 0)
        sensitive_blocks=$(grep -c "SENSITIVE_BLOCKED" "$AUDIT_LOG" || echo 0)
    fi
    
    # Get current clipboard status
    local current_content_length=0
    local clipboard_content
    clipboard_content=$(pbpaste 2>/dev/null || echo "")
    
    if [[ -n "$clipboard_content" ]]; then
        current_content_length=${#clipboard_content}
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "clipboard_usage",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "user": "$(whoami)",
    "os_version": "$(sw_vers -productVersion)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
  },
  "usage_statistics": {
    "total_operations": $total_operations,
    "copy_operations": $copy_operations,
    "paste_operations": $paste_operations,
    "blocked_operations": $blocked_operations,
    "sensitive_content_blocks": $sensitive_blocks
  },
  "current_status": {
    "clipboard_has_content": $([ -n "$clipboard_content" ] && echo true || echo false),
    "content_length": $current_content_length,
    "last_access": "$(tail -1 "$AUDIT_LOG" 2>/dev/null | awk '{print $1 " " $2}' || echo 'N/A')"
  },
  "policy_compliance": {
    "monitoring_enabled": $MONITOR_CLIPBOARD_CHANGES,
    "access_restrictions": $RESTRICT_CLIPBOARD_ACCESS,
    "content_filtering": $FILTER_SENSITIVE_DATA,
    "audit_logging": $AUDIT_CLIPBOARD_ACCESS
  },
  "security_events": {
    "blocked_applications": $blocked_operations,
    "sensitive_data_blocks": $sensitive_blocks,
    "policy_violations": $((blocked_operations + sensitive_blocks))
  }
}
EOF
    
    echo "Clipboard usage report saved to: $report_file"
    log_action "Clipboard usage report generated: $report_file"
}

# Clear clipboard securely
secure_clipboard_clear() {
    echo "=== Secure Clipboard Clear ==="
    
    # Clear clipboard multiple times to ensure data removal
    for i in {1..3}; do
        echo "" | pbcopy
        sleep 0.1
    done
    
    # Verify clearing
    local remaining_content
    remaining_content=$(pbpaste)
    
    if [[ -z "$remaining_content" ]]; then
        echo "✅ Clipboard cleared securely"
        log_action "Clipboard cleared securely"
        audit_log "SECURE_CLEAR" "N/A" "System"
        return 0
    else
        echo "⚠️  Clipboard may still contain data"
        log_action "WARNING: Clipboard clear verification failed"
        return 1
    fi
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Clipboard Management Tool Started ==="
    
    case "${1:-help}" in
        "copy")
            enterprise_clipboard_copy "$2" "$3" "$4"
            ;;
        "paste")
            enterprise_clipboard_paste "$2"
            ;;
        "deploy")
            deploy_enterprise_content "$2" "$3"
            ;;
        "monitor")
            monitor_clipboard
            ;;
        "clear")
            secure_clipboard_clear
            ;;
        "report")
            generate_clipboard_report
            ;;
        "status")
            echo "Current clipboard status:"
            enterprise_clipboard_paste "System" | head -5
            ;;
        "help"|*)
            echo "Roundfleet Clipboard Management Tool"
            echo "Usage: $0 [command] [options]"
            echo ""
            echo "Commands:"
            echo "  copy <content> [app] [force]  - Copy content to clipboard"
            echo "  paste [app]                   - Retrieve clipboard content"
            echo "  deploy <template> [users]     - Deploy enterprise content"
            echo "  monitor                       - Monitor clipboard changes"
            echo "  clear                         - Securely clear clipboard"
            echo "  report                        - Generate usage report"
            echo "  status                        - Show clipboard status"
            echo "  help                          - Show this help message"
            ;;
    esac
    
    log_action "=== Clipboard management operation completed ==="
}

# Execute main function
main "$@"

Advanced Clipboard Management

Content Template System

#!/bin/bash

# Enterprise content template management
manage_content_templates() {
    local action="$1"
    local template_name="$2"
    local template_content="$3"
    
    echo "=== Content Template Management ==="
    
    # Ensure templates directory exists
    mkdir -p "$CONTENT_TEMPLATES_DIR"
    
    case "$action" in
        "create")
            if [[ -z "$template_name" || -z "$template_content" ]]; then
                echo "❌ Template name and content required"
                return 1
            fi
            
            # Create template file
            echo "$template_content" > "$CONTENT_TEMPLATES_DIR/$template_name.txt"
            echo "✅ Template '$template_name' created"
            log_action "Template created: $template_name"
            ;;
        "list")
            echo "Available templates:"
            ls -1 "$CONTENT_TEMPLATES_DIR"/*.txt 2>/dev/null | xargs -I {} basename {} .txt || echo "No templates found"
            ;;
        "delete")
            if [[ -f "$CONTENT_TEMPLATES_DIR/$template_name.txt" ]]; then
                rm "$CONTENT_TEMPLATES_DIR/$template_name.txt"
                echo "✅ Template '$template_name' deleted"
                log_action "Template deleted: $template_name"
            else
                echo "❌ Template '$template_name' not found"
            fi
            ;;
        "show")
            if [[ -f "$CONTENT_TEMPLATES_DIR/$template_name.txt" ]]; then
                echo "Template '$template_name' content:"
                cat "$CONTENT_TEMPLATES_DIR/$template_name.txt"
            else
                echo "❌ Template '$template_name' not found"
            fi
            ;;
        *)
            echo "Usage: manage_content_templates [create|list|delete|show] [template_name] [content]"
            ;;
    esac
}

# Example template creation
create_default_templates() {
    # Support contact template
    manage_content_templates "create" "support_contact" "IT Support: [email protected] | Phone: +1-555-0123 | Portal: https://support.company.com"
    
    # Meeting link template  
    manage_content_templates "create" "meeting_link" "Join our meeting: https://meet.company.com/{{USER}}-{{TIMESTAMP}}"
    
    # Security reminder
    manage_content_templates "create" "security_reminder" "Security Reminder: Never share passwords or sensitive information via clipboard. Report suspicious activity to [email protected]"
    
    # Emergency contact
    manage_content_templates "create" "emergency_contact" "Emergency IT Support: +1-555-HELP (4357) | Available 24/7 | Incident Report: [email protected]"
}

create_default_templates

Clipboard History Management

#!/bin/bash

# Advanced clipboard history with encryption
manage_clipboard_history() {
    local action="$1"
    local history_file="$CACHE_DIR/clipboard_history.enc"
    local max_history_items=50
    
    echo "=== Clipboard History Management ==="
    
    case "$action" in
        "save")
            local current_content
            current_content=$(pbpaste)
            
            if [[ -n "$current_content" ]]; then
                # Create history entry
                local timestamp
                timestamp=$(date '+%Y-%m-%d %H:%M:%S')
                local content_hash
                content_hash=$(echo "$current_content" | md5)
                
                # Encrypt and save if sensitive content handling is enabled
                if [[ "$ENCRYPT_SENSITIVE_CONTENT" == "true" ]]; then
                    echo "$timestamp|$content_hash|$(echo "$current_content" | base64)" >> "$history_file.tmp"
                else
                    echo "$timestamp|$content_hash|$current_content" >> "$history_file.tmp"
                fi
                
                # Keep only last N items
                tail -$max_history_items "$history_file.tmp" > "$history_file"
                rm "$history_file.tmp"
                
                echo "✅ Clipboard content saved to history"
                log_action "Clipboard history saved - Hash: $content_hash"
            fi
            ;;
        "list")
            if [[ -f "$history_file" ]]; then
                echo "Recent clipboard history:"
                cat "$history_file" | while IFS='|' read -r timestamp hash content; do
                    if [[ "$ENCRYPT_SENSITIVE_CONTENT" == "true" ]]; then
                        content=$(echo "$content" | base64 -d | head -c 50)
                    else
                        content=$(echo "$content" | head -c 50)
                    fi
                    echo "[$timestamp] $hash: ${content}..."
                done
            else
                echo "No clipboard history found"
            fi
            ;;
        "restore")
            local item_number="$2"
            if [[ -f "$history_file" && -n "$item_number" ]]; then
                local line_content
                line_content=$(sed -n "${item_number}p" "$history_file")
                
                if [[ -n "$line_content" ]]; then
                    local content
                    content=$(echo "$line_content" | cut -d'|' -f3-)
                    
                    if [[ "$ENCRYPT_SENSITIVE_CONTENT" == "true" ]]; then
                        content=$(echo "$content" | base64 -d)
                    fi
                    
                    echo "$content" | pbcopy
                    echo "✅ Clipboard restored from history item $item_number"
                    log_action "Clipboard restored from history item $item_number"
                else
                    echo "❌ History item $item_number not found"
                fi
            else
                echo "❌ Invalid item number or no history file"
            fi
            ;;
        "clear")
            if [[ -f "$history_file" ]]; then
                rm "$history_file"
                echo "✅ Clipboard history cleared"
                log_action "Clipboard history cleared"
            else
                echo "No history file to clear"
            fi
            ;;
        *)
            echo "Usage: manage_clipboard_history [save|list|restore|clear] [item_number]"
            ;;
    esac
}

# Auto-save clipboard changes to history
auto_save_clipboard() {
    if [[ "$MONITOR_CLIPBOARD_CHANGES" == "true" ]]; then
        # Save current content to history
        manage_clipboard_history "save"
    fi
}

# Example usage:
# manage_clipboard_history "list"
# manage_clipboard_history "restore" 3

Cross-Application Clipboard Policies

#!/bin/bash

# Application-specific clipboard policies
manage_app_policies() {
    local action="$1"
    local app_name="$2"
    local policy_type="$3"
    
    local policies_file="$CACHE_DIR/app_policies.conf"
    
    echo "=== Application Clipboard Policies ==="
    
    case "$action" in
        "set")
            # Set policy for specific application
            if [[ -z "$app_name" || -z "$policy_type" ]]; then
                echo "❌ Application name and policy type required"
                return 1
            fi
            
            # Remove existing policy
            grep -v "^$app_name:" "$policies_file" > "$policies_file.tmp" 2>/dev/null || touch "$policies_file.tmp"
            
            # Add new policy
            echo "$app_name:$policy_type" >> "$policies_file.tmp"
            mv "$policies_file.tmp" "$policies_file"
            
            echo "✅ Policy set for $app_name: $policy_type"
            log_action "App policy set - $app_name: $policy_type"
            ;;
        "get")
            if [[ -f "$policies_file" && -n "$app_name" ]]; then
                local policy
                policy=$(grep "^$app_name:" "$policies_file" | cut -d':' -f2)
                
                if [[ -n "$policy" ]]; then
                    echo "Policy for $app_name: $policy"
                else
                    echo "No specific policy for $app_name (using default)"
                fi
            else
                echo "No policies configured"
            fi
            ;;
        "list")
            if [[ -f "$policies_file" ]]; then
                echo "Configured application policies:"
                cat "$policies_file" | while IFS=':' read -r app policy; do
                    echo "  $app: $policy"
                done
            else
                echo "No policies configured"
            fi
            ;;
        "remove")
            if [[ -f "$policies_file" && -n "$app_name" ]]; then
                grep -v "^$app_name:" "$policies_file" > "$policies_file.tmp"
                mv "$policies_file.tmp" "$policies_file"
                echo "✅ Policy removed for $app_name"
                log_action "App policy removed - $app_name"
            else
                echo "❌ No policy found for $app_name"
            fi
            ;;
        *)
            echo "Usage: manage_app_policies [set|get|list|remove] [app_name] [policy_type]"
            echo "Policy types: allow, block, monitor, restricted"
            ;;
    esac
}

# Check application policy before clipboard operation
check_app_policy() {
    local app_name="$1"
    local operation="$2"
    local policies_file="$CACHE_DIR/app_policies.conf"
    
    if [[ -f "$policies_file" ]]; then
        local policy
        policy=$(grep "^$app_name:" "$policies_file" | cut -d':' -f2)
        
        case "$policy" in
            "block")
                echo "❌ Application $app_name is blocked from clipboard operations"
                return 1
                ;;
            "restricted")
                echo "⚠️  Application $app_name has restricted clipboard access"
                # Additional checks could be implemented here
                return 0
                ;;
            "monitor")
                echo "🔍 Monitoring clipboard access for $app_name"
                audit_log "MONITORED_ACCESS" "N/A" "$app_name"
                return 0
                ;;
            "allow"|*)
                return 0
                ;;
        esac
    else
        # Default policy
        return 0
    fi
}

# Example policy setup
setup_default_policies() {
    manage_app_policies "set" "Terminal" "monitor"
    manage_app_policies "set" "Script Editor" "restricted"
    manage_app_policies "set" "TextEdit" "allow"
    manage_app_policies "set" "Mail" "allow"
    manage_app_policies "set" "Slack" "allow"
    manage_app_policies "set" "Suspicious App" "block"
}

setup_default_policies

Monitoring and Compliance

Real-time Clipboard Monitoring

#!/bin/bash

# Advanced clipboard monitoring with alerts
advanced_clipboard_monitor() {
    echo "=== Advanced Clipboard Monitoring ==="
    
    local monitor_pid_file="$CACHE_DIR/clipboard_monitor.pid"
    local alert_threshold=10  # Alert after 10 sensitive content detections per hour
    local sensitive_count=0
    local hour_start=$(date +%H)
    
    # Store monitor PID
    echo $$ > "$monitor_pid_file"
    
    echo "Starting advanced clipboard monitoring..."
    echo "Monitor PID: $$"
    
    # Cleanup function
    cleanup() {
        echo "Stopping clipboard monitor..."
        rm -f "$monitor_pid_file"
        exit 0
    }
    
    trap cleanup SIGTERM SIGINT
    
    local previous_content=""
    
    while true; do
        local current_content
        current_content=$(pbpaste 2>/dev/null || echo "")
        local current_hour
        current_hour=$(date +%H)
        
        # Reset counter each hour
        if [[ "$current_hour" != "$hour_start" ]]; then
            sensitive_count=0
            hour_start="$current_hour"
        fi
        
        # Check for content changes
        if [[ "$current_content" != "$previous_content" && -n "$current_content" ]]; then
            local timestamp
            timestamp=$(date '+%Y-%m-%d %H:%M:%S')
            
            echo "[$timestamp] Clipboard content changed"
            
            # Get current application
            local current_app
            current_app=$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' 2>/dev/null || echo "Unknown")
            
            # Check for sensitive content
            if violations=$(detect_sensitive_data "$current_content"); then
                ((sensitive_count++))
                
                echo "⚠️  SECURITY ALERT: Sensitive data detected!"
                echo "Application: $current_app"
                echo "Violations: $violations"
                
                # Log security event
                log_action "SECURITY ALERT: Sensitive data in clipboard - App: $current_app - Violations: $violations"
                audit_log "SENSITIVE_DETECTED" "$(echo "$current_content" | md5)" "$current_app"
                
                # Check alert threshold
                if [[ $sensitive_count -ge $alert_threshold ]]; then
                    echo "🚨 COMPLIANCE ALERT: Sensitive content threshold exceeded ($sensitive_count violations this hour)"
                    log_action "COMPLIANCE ALERT: Sensitive content threshold exceeded - $sensitive_count violations"
                    
                    # Could trigger additional security measures here
                    # send_security_alert "$current_app" "$violations"
                fi
            fi
            
            # Check application policy
            check_app_policy "$current_app" "copy"
            
            # Auto-save to history if enabled
            if [[ "$MONITOR_CLIPBOARD_CHANGES" == "true" ]]; then
                auto_save_clipboard
            fi
            
            previous_content="$current_content"
        fi
        
        sleep 1
    done
}

# Start monitoring in background
start_clipboard_monitor() {
    local monitor_pid_file="$CACHE_DIR/clipboard_monitor.pid"
    
    if [[ -f "$monitor_pid_file" ]]; then
        local existing_pid
        existing_pid=$(cat "$monitor_pid_file")
        
        if kill -0 "$existing_pid" 2>/dev/null; then
            echo "Clipboard monitor already running (PID: $existing_pid)"
            return 0
        else
            echo "Cleaning up stale monitor PID file"
            rm -f "$monitor_pid_file"
        fi
    fi
    
    echo "Starting clipboard monitor in background..."
    advanced_clipboard_monitor &
    local monitor_pid=$!
    
    echo "Clipboard monitor started (PID: $monitor_pid)"
    return 0
}

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

# Example usage:
# start_clipboard_monitor
# stop_clipboard_monitor

Compliance Reporting and Audit

#!/bin/bash

# Comprehensive compliance reporting
generate_compliance_report() {
    local report_period="${1:-daily}"
    local output_format="${2:-json}"
    
    echo "=== Generating Compliance Report ==="
    echo "Period: $report_period"
    echo "Format: $output_format"
    
    local report_file="$CACHE_DIR/compliance_report_${report_period}_$(date +%Y%m%d_%H%M%S).$output_format"
    
    # Calculate date range
    local start_date
    local end_date
    end_date=$(date +%Y-%m-%d)
    
    case "$report_period" in
        "daily")
            start_date=$(date +%Y-%m-%d)
            ;;
        "weekly")
            start_date=$(date -d '7 days ago' +%Y-%m-%d 2>/dev/null || date -v-7d +%Y-%m-%d)
            ;;
        "monthly")
            start_date=$(date -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -v-30d +%Y-%m-%d)
            ;;
        *)
            start_date=$(date +%Y-%m-%d)
            ;;
    esac
    
    # Analyze audit logs
    local total_operations=0
    local security_violations=0
    local blocked_operations=0
    local unique_apps=0
    
    if [[ -f "$AUDIT_LOG" ]]; then
        # Filter logs by date range
        local filtered_logs
        filtered_logs=$(awk -v start="$start_date" -v end="$end_date" '$1 >= start && $1 <= end' "$AUDIT_LOG")
        
        total_operations=$(echo "$filtered_logs" | wc -l)
        security_violations=$(echo "$filtered_logs" | grep -c "SENSITIVE" || echo 0)
        blocked_operations=$(echo "$filtered_logs" | grep -c "BLOCKED" || echo 0)
        unique_apps=$(echo "$filtered_logs" | awk '{print $4}' | sort -u | wc -l)
    fi
    
    # Generate report based on format
    if [[ "$output_format" == "json" ]]; then
        cat > "$report_file" << EOF
{
  "report_type": "clipboard_compliance",
  "period": "$report_period",
  "date_range": {
    "start": "$start_date",
    "end": "$end_date"
  },
  "generated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "user": "$(whoami)",
    "os_version": "$(sw_vers -productVersion)"
  },
  "compliance_metrics": {
    "total_clipboard_operations": $total_operations,
    "security_violations": $security_violations,
    "blocked_operations": $blocked_operations,
    "unique_applications": $unique_apps,
    "compliance_score": $(( 100 - (security_violations * 10) - (blocked_operations * 5) ))
  },
  "policy_status": {
    "monitoring_enabled": $MONITOR_CLIPBOARD_CHANGES,
    "content_filtering": $FILTER_SENSITIVE_DATA,
    "access_control": $RESTRICT_CLIPBOARD_ACCESS,
    "audit_logging": $AUDIT_CLIPBOARD_ACCESS
  },
  "recommendations": [
    $([ $security_violations -gt 5 ] && echo '"Increase security training for users",' || echo "")
    $([ $blocked_operations -gt 10 ] && echo '"Review application access policies",' || echo "")
    "Regular policy review and updates"
  ]
}
EOF
    else
        # Plain text format
        cat > "$report_file" << EOF
Roundfleet Clipboard Compliance Report
===================================
Generated: $(date)
Period: $report_period ($start_date to $end_date)
Device: $(hostname) ($(whoami))

COMPLIANCE METRICS:
- Total clipboard operations: $total_operations
- Security violations: $security_violations
- Blocked operations: $blocked_operations
- Unique applications: $unique_apps
- Compliance score: $(( 100 - (security_violations * 10) - (blocked_operations * 5) ))%

POLICY STATUS:
- Monitoring enabled: $MONITOR_CLIPBOARD_CHANGES
- Content filtering: $FILTER_SENSITIVE_DATA
- Access control: $RESTRICT_CLIPBOARD_ACCESS
- Audit logging: $AUDIT_CLIPBOARD_ACCESS

RECOMMENDATIONS:
EOF
        
        if [[ $security_violations -gt 5 ]]; then
            echo "- Increase security training for users" >> "$report_file"
        fi
        
        if [[ $blocked_operations -gt 10 ]]; then
            echo "- Review application access policies" >> "$report_file"
        fi
        
        echo "- Regular policy review and updates" >> "$report_file"
    fi
    
    echo "Compliance report generated: $report_file"
    log_action "Compliance report generated: $report_file"
}

# Example usage:
# generate_compliance_report "weekly" "json"
# generate_compliance_report "monthly" "txt"

Important Configuration Notes

macOS Clipboard Security

  • Pasteboard types - Support for different data formats
  • Application sandboxing - Clipboard access restrictions
  • Privacy permissions - User consent requirements
  • Secure coding - Protection against injection attacks

Enterprise Integration Points

  • MDM integration - Deploy clipboard policies via configuration profiles
  • SIEM integration - Send audit logs to security systems
  • Identity management - Integrate with corporate directory services
  • Compliance frameworks - Support for regulatory requirements

Best Practices for Enterprise

  1. Security-First Approach

    • Filter sensitive content automatically
    • Monitor clipboard operations continuously
    • Implement application access controls
    • Maintain comprehensive audit trails
  2. User Experience Balance

    • Provide clear feedback on policy violations
    • Allow legitimate business workflows
    • Minimize performance impact
    • Offer self-service compliance tools
  3. Policy Management

    • Define clear clipboard usage policies
    • Regularly review and update rules
    • Train users on security requirements
    • Monitor compliance metrics
  4. Incident Response

    • Detect sensitive data exposure quickly
    • Provide automated remediation options
    • Generate compliance reports regularly
    • Integrate with security incident workflows

Troubleshooting Common Issues

  • Permission errors - Check accessibility and automation permissions
  • Application blocks - Review application access policies
  • Content filtering - Adjust sensitivity detection rules
  • Performance impact - Optimize monitoring frequency
  • Audit log growth - Implement log rotation and archival

Remember to test clipboard management procedures thoroughly and ensure they align with your organization's security policies and compliance requirements before deploying across your entire Roundfleet.

Cisco Umbrella Roaming Client Management on macOS

Deploy and manage Cisco Umbrella roaming clients across your Roundfleet with enterprise-grade security DNS protection, automated deployment workflows, and comprehensive monitoring capabilities. This tutorial transforms the basic deployment process into a robust enterprise security solution.

Understanding Enterprise Cisco Umbrella Management

Enterprise Cisco Umbrella deployment requires more than basic client installation, demanding:

  • Automated deployment workflows with organization-specific configurations
  • Centralized security policy management with DNS filtering controls
  • Real-time monitoring and reporting of security threats and activities
  • Certificate management for advanced security features
  • Compliance tracking for security posture management
  • Integration capabilities with existing security infrastructure

Core Cisco Umbrella Deployment Process

Basic Deployment Components

  1. Configuration Push - Deploy OrgInfo.plist with organization parameters
  2. PKG Installation - Install the Umbrella roaming client application
  3. Certificate Distribution - Deploy root certificates for advanced features
  4. Policy Application - Configure security policies and monitoring

Core Configuration Script

# Basic configuration script
mkdir "/Library/Application Support/OpenDNS Roaming Client/"
cat <<EOF > "/Library/Application Support/OpenDNS Roaming Client/OrgInfo.plist"
<?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>APIFingerprint</key>
    <string>xxxxxxxxxxx</string>
    <key>APIOrganizationID</key>
    <string>xxxxxx</string>
    <key>APIUserID</key>
    <string>xxxxx</string>
    <key>InstallMenubar</key>
    <false/>
</dict>
</plist>
EOF

Enterprise Cisco Umbrella Management System

#!/bin/bash

# Roundfleet Enterprise Cisco Umbrella Management System
# Comprehensive security DNS deployment with enterprise controls and monitoring

# Configuration
SCRIPT_NAME="Roundfleet Cisco Umbrella Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_umbrella.log"
AUDIT_LOG="/var/log/roundfleet_umbrella_audit.log"
CONFIG_DIR="/Library/Application Support/OpenDNS Roaming Client"
UMBRELLA_CONFIG="$CONFIG_DIR/OrgInfo.plist"
CERTS_DIR="/etc/roundfleet/umbrella/certificates"
POLICIES_DIR="/etc/roundfleet/umbrella/policies"
TEMP_DIR="/tmp/roundfleet_umbrella"
BACKUP_DIR="/var/backups/umbrella"
MONITORING_INTERVAL=300  # 5 minutes
HEALTH_CHECK_TIMEOUT=30
ORGANIZATION_NAME="Roundfleet Enterprise"
DEPLOYMENT_MODE="enterprise"
ENABLE_ADVANCED_FEATURES=true
ENABLE_THREAT_MONITORING=true
AUTO_CERTIFICATE_RENEWAL=true

# Umbrella Configuration Parameters (to be customized per organization)
declare -A UMBRELLA_CONFIG_PARAMS=(
    ["APIFingerprint"]=""           # To be populated from Cisco dashboard
    ["APIOrganizationID"]=""        # To be populated from Cisco dashboard
    ["APIUserID"]=""                # To be populated from Cisco dashboard
    ["InstallMenubar"]="false"
    ["EnableLogging"]="true"
    ["LogLevel"]="INFO"
    ["UpdateInterval"]="3600"
    ["BackupDNS"]="8.8.8.8,1.1.1.1"
    ["EnforceSecureDNS"]="true"
    ["BlockMalware"]="true"
    ["BlockPhishing"]="true"
    ["BlockAdware"]="true"
    ["ContentFiltering"]="true"
    ["SafeSearch"]="true"
    ["YouTubeFiltering"]="strict"
)

# Security Policy Templates
declare -A SECURITY_POLICIES=(
    ["executive"]="high_security_minimal_blocking"
    ["standard"]="balanced_security_moderate_blocking"
    ["guest"]="basic_security_extensive_blocking"
    ["developer"]="medium_security_minimal_blocking"
    ["kiosk"]="maximum_security_extensive_blocking"
)

# Create necessary directories
mkdir -p "$CONFIG_DIR"
mkdir -p "$CERTS_DIR"
mkdir -p "$POLICIES_DIR"
mkdir -p "$TEMP_DIR"
mkdir -p "$BACKUP_DIR"
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$AUDIT_LOG")"

# Set secure permissions
chmod 755 "$CONFIG_DIR"
chmod 700 "$CERTS_DIR"
chmod 750 "$POLICIES_DIR"
chmod 700 "$TEMP_DIR"
chmod 750 "$BACKUP_DIR"

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

log_security_event() {
    local event_type="$1"
    local details="$2"
    local severity="$3"
    local admin_user=$(whoami)
    
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    local source_ip=$(who am i | awk '{print $5}' | tr -d '()')
    echo "SECURITY|$timestamp|$event_type|$severity|$admin_user|$source_ip|$details" >> "$AUDIT_LOG"
}

# Validate Cisco Umbrella configuration parameters
validate_umbrella_config() {
    local errors=()
    
    # Check required API parameters
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" ]]; then
        errors+=("APIFingerprint is required")
    fi
    
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIOrganizationID]}" ]]; then
        errors+=("APIOrganizationID is required")
    fi
    
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIUserID]}" ]]; then
        errors+=("APIUserID is required")
    fi
    
    # Validate fingerprint format (basic check)
    if [[ -n "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" ]] && [[ ! "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" =~ ^[A-Fa-f0-9]{40,}$ ]]; then
        errors+=("APIFingerprint format appears invalid")
    fi
    
    if [[ ${#errors[@]} -gt 0 ]]; then
        echo "Umbrella configuration validation failed:"
        printf '  - %s\n' "${errors[@]}"
        return 1
    fi
    
    return 0
}

# Generate enterprise Umbrella configuration
generate_umbrella_config() {
    local user_profile="${1:-standard}"
    local custom_settings="${2:-}"
    local admin_user=$(whoami)
    
    log_security_event "CONFIG_GENERATION" "profile=$user_profile" "INFO"
    
    echo "=== Generating Cisco Umbrella Configuration ==="
    echo "User Profile: $user_profile"
    echo "Deployment Mode: $DEPLOYMENT_MODE"
    echo "Administrator: $admin_user"
    echo ""
    
    # Validate configuration before generation
    if ! validate_umbrella_config; then
        log_operation "ERROR" "Configuration validation failed"
        return 1
    fi
    
    # Backup existing configuration
    if [[ -f "$UMBRELLA_CONFIG" ]]; then
        local backup_file="$BACKUP_DIR/OrgInfo_$(date +%Y%m%d_%H%M%S).plist"
        cp "$UMBRELLA_CONFIG" "$backup_file"
        log_operation "INFO" "Existing configuration backed up to: $backup_file"
    fi
    
    # Apply profile-specific security settings
    case "$user_profile" in
        "executive")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="WARN"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="false"
            ;;
        "standard")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="INFO"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            ;;
        "guest")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="WARN"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            UMBRELLA_CONFIG_PARAMS["SafeSearch"]="true"
            ;;
        "developer")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="DEBUG"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="true"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="false"
            ;;
        "kiosk")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="ERROR"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            UMBRELLA_CONFIG_PARAMS["EnforceSecureDNS"]="true"
            ;;
    esac
    
    # Generate the configuration file
    cat > "$UMBRELLA_CONFIG" << 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>
    <!-- Core Cisco Umbrella API Configuration -->
    <key>APIFingerprint</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}</string>
    <key>APIOrganizationID</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIOrganizationID]}</string>
    <key>APIUserID</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIUserID]}</string>
    
    <!-- Enterprise UI Configuration -->
    <key>InstallMenubar</key>
    <${UMBRELLA_CONFIG_PARAMS[InstallMenubar]}/>
    <key>ShowNotifications</key>
    <true/>
    <key>AutoStart</key>
    <true/>
    
    <!-- Logging and Monitoring -->
    <key>EnableLogging</key>
    <${UMBRELLA_CONFIG_PARAMS[EnableLogging]}/>
    <key>LogLevel</key>
    <string>${UMBRELLA_CONFIG_PARAMS[LogLevel]}</string>
    <key>LogRotationDays</key>
    <integer>30</integer>
    
    <!-- Network Configuration -->
    <key>UpdateInterval</key>
    <integer>${UMBRELLA_CONFIG_PARAMS[UpdateInterval]}</integer>
    <key>BackupDNS</key>
    <string>${UMBRELLA_CONFIG_PARAMS[BackupDNS]}</string>
    <key>EnforceSecureDNS</key>
    <${UMBRELLA_CONFIG_PARAMS[EnforceSecureDNS]}/>
    
    <!-- Security Policies -->
    <key>BlockMalware</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockMalware]}/>
    <key>BlockPhishing</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockPhishing]}/>
    <key>BlockAdware</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockAdware]}/>
    
    <!-- Content Filtering -->
    <key>ContentFiltering</key>
    <${UMBRELLA_CONFIG_PARAMS[ContentFiltering]}/>
    <key>SafeSearch</key>
    <${UMBRELLA_CONFIG_PARAMS[SafeSearch]}/>
    <key>YouTubeFiltering</key>
    <string>${UMBRELLA_CONFIG_PARAMS[YouTubeFiltering]}</string>
    
    <!-- Enterprise Metadata -->
    <key>OrganizationName</key>
    <string>$ORGANIZATION_NAME</string>
    <key>DeploymentMode</key>
    <string>$DEPLOYMENT_MODE</string>
    <key>ConfigurationVersion</key>
    <string>$(date +%Y%m%d%H%M%S)</string>
    <key>DeployedBy</key>
    <string>$admin_user</string>
    <key>DeploymentDate</key>
    <string>$(date)</string>
    <key>UserProfile</key>
    <string>$user_profile</string>
</dict>
</plist>
EOF
    
    # Set secure permissions
    chmod 644 "$UMBRELLA_CONFIG"
    chown root:wheel "$UMBRELLA_CONFIG"
    
    # Validate generated configuration
    if plutil -lint "$UMBRELLA_CONFIG" &>/dev/null; then
        echo "✅ Configuration generated successfully"
        log_operation "INFO" "Umbrella configuration generated for profile: $user_profile"
        log_security_event "CONFIG_DEPLOYED" "profile=$user_profile,file=$UMBRELLA_CONFIG" "INFO"
        return 0
    else
        echo "❌ Configuration validation failed"
        log_operation "ERROR" "Generated configuration file is invalid"
        return 1
    fi
}

# Install Cisco Umbrella certificates
install_umbrella_certificates() {
    local cert_source="${1:-auto}"
    local admin_user=$(whoami)
    
    log_security_event "CERT_INSTALLATION" "source=$cert_source" "INFO"
    
    echo "=== Installing Cisco Umbrella Certificates ==="
    echo "Certificate Source: $cert_source"
    echo "Administrator: $admin_user"
    echo ""
    
    local cert_files=()
    
    case "$cert_source" in
        "auto")
            # Download certificates from Cisco (requires authentication)
            echo "Downloading latest Cisco Umbrella root certificates..."
            
            # Note: In production, these would be downloaded from Cisco portal
            # For this example, we'll check for pre-downloaded certificates
            if [[ -f "$CERTS_DIR/cisco_umbrella_root.pem" ]]; then
                cert_files+=("$CERTS_DIR/cisco_umbrella_root.pem")
            else
                echo "⚠️  Certificate files not found in $CERTS_DIR"
                echo "Please download certificates from Cisco Umbrella portal:"
                echo "Deployments > Configuration > Root Certificate"
                return 1
            fi
            ;;
        "local")
            # Use locally provided certificates
            cert_files=($(find "$CERTS_DIR" -name "*.pem" -o -name "*.crt" -o -name "*.cer"))
            ;;
        *)
            # Specific certificate file
            if [[ -f "$cert_source" ]]; then
                cert_files=("$cert_source")
            else
                echo "Certificate file not found: $cert_source"
                return 1
            fi
            ;;
    esac
    
    if [[ ${#cert_files[@]} -eq 0 ]]; then
        echo "No certificate files found"
        return 1
    fi
    
    # Install certificates
    local installed_count=0
    for cert_file in "${cert_files[@]}"; do
        echo "Installing certificate: $(basename "$cert_file")"
        
        # Verify certificate before installation
        if openssl x509 -in "$cert_file" -text -noout &>/dev/null; then
            # Install to system keychain
            if security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$cert_file"; then
                echo "✅ Certificate installed successfully"
                installed_count=$((installed_count + 1))
                log_operation "INFO" "Certificate installed: $(basename "$cert_file")"
            else
                echo "❌ Failed to install certificate: $(basename "$cert_file")"
                log_operation "ERROR" "Certificate installation failed: $(basename "$cert_file")"
            fi
        else
            echo "❌ Invalid certificate format: $(basename "$cert_file")"
            log_operation "ERROR" "Invalid certificate format: $(basename "$cert_file")"
        fi
    done
    
    echo ""
    echo "Certificate installation completed: $installed_count/${#cert_files[@]} successful"
    
    if [[ $installed_count -gt 0 ]]; then
        log_security_event "CERTS_INSTALLED" "count=$installed_count" "INFO"
        return 0
    else
        log_security_event "CERT_INSTALL_FAILED" "all_failed=true" "ERROR"
        return 1
    fi
}

# Monitor Cisco Umbrella service health
monitor_umbrella_health() {
    local check_type="${1:-basic}"
    local admin_user=$(whoami)
    
    echo "=== Cisco Umbrella Health Monitoring ==="
    echo "Check Type: $check_type"
    echo "Monitor: $admin_user"
    echo ""
    
    local health_status="HEALTHY"
    local issues=()
    
    # Check if configuration file exists and is valid
    if [[ ! -f "$UMBRELLA_CONFIG" ]]; then
        health_status="CRITICAL"
        issues+=("Configuration file missing")
    elif ! plutil -lint "$UMBRELLA_CONFIG" &>/dev/null; then
        health_status="CRITICAL"
        issues+=("Configuration file corrupted")
    fi
    
    # Check if Umbrella process is running
    if ! pgrep -f "Umbrella" &>/dev/null; then
        health_status="WARNING"
        issues+=("Umbrella client not running")
    fi
    
    # Check DNS resolution through Umbrella
    echo "Testing DNS resolution through Cisco Umbrella..."
    local test_domains=("cisco.com" "umbrella.com" "google.com")
    local dns_failures=0
    
    for domain in "${test_domains[@]}"; do
        if timeout "$HEALTH_CHECK_TIMEOUT" nslookup "$domain" &>/dev/null; then
            echo "✅ DNS resolution successful: $domain"
        else
            echo "❌ DNS resolution failed: $domain"
            dns_failures=$((dns_failures + 1))
        fi
    done
    
    if [[ $dns_failures -gt 0 ]]; then
        health_status="WARNING"
        issues+=("DNS resolution issues ($dns_failures failed)")
    fi
    
    # Check certificate validity
    echo ""
    echo "Checking Cisco Umbrella certificates..."
    local expired_certs=0
    
    # Get Umbrella-related certificates from system keychain
    local umbrella_certs=$(security find-certificate -a -c "Cisco" /Library/Keychains/System.keychain 2>/dev/null | grep "alis" | wc -l)
    
    if [[ $umbrella_certs -eq 0 ]]; then
        health_status="WARNING"
        issues+=("No Cisco certificates found")
    else
        echo "✅ Found $umbrella_certs Cisco certificates"
    fi
    
    # Advanced checks
    if [[ "$check_type" == "comprehensive" ]]; then
        echo ""
        echo "Running comprehensive health checks..."
        
        # Check log file for errors
        if [[ -f "/Library/Logs/OpenDNSRoamingClient.log" ]]; then
            local recent_errors=$(tail -100 "/Library/Logs/OpenDNSRoamingClient.log" 2>/dev/null | grep -i "error" | wc -l)
            if [[ $recent_errors -gt 5 ]]; then
                health_status="WARNING"
                issues+=("High error count in logs ($recent_errors)")
            fi
        fi
        
        # Check network connectivity to Umbrella servers
        local umbrella_servers=("208.67.222.222" "208.67.220.220")
        for server in "${umbrella_servers[@]}"; do
            if timeout 5 ping -c 1 "$server" &>/dev/null; then
                echo "✅ Connectivity to Umbrella server: $server"
            else
                echo "❌ Cannot reach Umbrella server: $server"
                health_status="WARNING"
                issues+=("Connectivity issues to $server")
            fi
        done
    fi
    
    # Generate health report
    echo ""
    echo "=== Health Status Report ==="
    echo "Overall Status: $health_status"
    echo "Timestamp: $(date)"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "Issues Found:"
        printf '  - %s\n' "${issues[@]}"
    else
        echo "✅ All systems operational"
    fi
    
    # Log health status
    log_operation "INFO" "Health check completed: $health_status (${#issues[@]} issues)"
    log_security_event "HEALTH_CHECK" "status=$health_status,issues=${#issues[@]}" "INFO"
    
    # Return appropriate exit code
    case "$health_status" in
        "HEALTHY") return 0 ;;
        "WARNING") return 1 ;;
        "CRITICAL") return 2 ;;
        *) return 3 ;;
    esac
}

# Generate Umbrella deployment report
generate_umbrella_report() {
    local report_type="${1:-summary}"
    local admin_user=$(whoami)
    local report_file="/var/reports/umbrella_report_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$report_file")"
    
    log_security_event "REPORT_GENERATION" "type=$report_type" "INFO"
    
    {
        echo "Roundfleet Cisco Umbrella Deployment Report"
        echo "========================================="
        echo "Report Type: $report_type"
        echo "Generated: $(date)"
        echo "Generated By: $admin_user"
        echo "Hostname: $(hostname)"
        echo ""
        
        case "$report_type" in
            "summary")
                echo "== Deployment Summary =="
                echo "Organization: $ORGANIZATION_NAME"
                echo "Deployment Mode: $DEPLOYMENT_MODE"
                echo "Configuration File: $UMBRELLA_CONFIG"
                
                if [[ -f "$UMBRELLA_CONFIG" ]]; then
                    echo "Configuration Status: Deployed"
                    local config_date=$(stat -f %Sm "$UMBRELLA_CONFIG")
                    echo "Last Modified: $config_date"
                else
                    echo "Configuration Status: Not Deployed"
                fi
                
                # Client status
                if pgrep -f "Umbrella" &>/dev/null; then
                    echo "Client Status: Running"
                else
                    echo "Client Status: Not Running"
                fi
                ;;
            "security")
                echo "== Security Assessment =="
                echo "Security Features Enabled:"
                
                if [[ -f "$UMBRELLA_CONFIG" ]]; then
                    local malware_blocking=$(plutil -extract BlockMalware xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Enabled" || echo "Disabled")
                    local phishing_blocking=$(plutil -extract BlockPhishing xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Enabled" || echo "Disabled")
                    local content_filtering=$(plutil -extract ContentFiltering xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Enabled" || echo "Disabled")
                    
                    echo "  Malware Blocking: $malware_blocking"
                    echo "  Phishing Blocking: $phishing_blocking"
                    echo "  Content Filtering: $content_filtering"
                else
                    echo "  Configuration not available for analysis"
                fi
                
                # Certificate status
                local cisco_certs=$(security find-certificate -a -c "Cisco" /Library/Keychains/System.keychain 2>/dev/null | grep "alis" | wc -l)
                echo "  Cisco Certificates Installed: $cisco_certs"
                ;;
            "audit")
                echo "== Audit Information =="
                if [[ -f "$AUDIT_LOG" ]]; then
                    echo "Recent security events (last 10):"
                    tail -10 "$AUDIT_LOG"
                else
                    echo "No audit log available"
                fi
                ;;
        esac
        
        echo ""
        echo "== Configuration Details =="
        if [[ -f "$UMBRELLA_CONFIG" ]]; then
            echo "Configuration file contents:"
            cat "$UMBRELLA_CONFIG"
        else
            echo "No configuration file found"
        fi
        
    } > "$report_file"
    
    echo "Umbrella deployment report generated: $report_file"
    log_operation "INFO" "Umbrella report generated: $report_file"
}

# Set organization-specific parameters
set_organization_params() {
    local api_fingerprint="$1"
    local api_org_id="$2"
    local api_user_id="$3"
    
    if [[ -z "$api_fingerprint" || -z "$api_org_id" || -z "$api_user_id" ]]; then
        echo "Usage: set_organization_params <api_fingerprint> <api_org_id> <api_user_id>"
        echo ""
        echo "These parameters can be obtained from:"
        echo "Cisco Umbrella Portal > Deployments > Core Identities > Roaming Computers"
        return 1
    fi
    
    UMBRELLA_CONFIG_PARAMS["APIFingerprint"]="$api_fingerprint"
    UMBRELLA_CONFIG_PARAMS["APIOrganizationID"]="$api_org_id"
    UMBRELLA_CONFIG_PARAMS["APIUserID"]="$api_user_id"
    
    echo "Organization parameters updated successfully"
    log_security_event "ORG_PARAMS_SET" "org_id=$api_org_id" "INFO"
}

# Main Cisco Umbrella management function
main() {
    local action="${1:-help}"
    
    case "$action" in
        "configure")
            local user_profile="${2:-standard}"
            local custom_settings="$3"
            
            generate_umbrella_config "$user_profile" "$custom_settings"
            ;;
        "install-certs")
            local cert_source="${2:-auto}"
            
            install_umbrella_certificates "$cert_source"
            ;;
        "health")
            local check_type="${2:-basic}"
            
            monitor_umbrella_health "$check_type"
            ;;
        "report")
            local report_type="${2:-summary}"
            
            generate_umbrella_report "$report_type"
            ;;
        "set-params")
            local api_fingerprint="$2"
            local api_org_id="$3"
            local api_user_id="$4"
            
            set_organization_params "$api_fingerprint" "$api_org_id" "$api_user_id"
            ;;
        "deploy")
            local user_profile="${2:-standard}"
            
            echo "=== Full Cisco Umbrella Deployment ==="
            echo "Starting comprehensive deployment..."
            echo ""
            
            # Step 1: Generate configuration
            if generate_umbrella_config "$user_profile"; then
                echo "✅ Configuration deployment successful"
            else
                echo "❌ Configuration deployment failed"
                exit 1
            fi
            
            echo ""
            
            # Step 2: Install certificates
            if install_umbrella_certificates "auto"; then
                echo "✅ Certificate installation successful"
            else
                echo "⚠️  Certificate installation had issues"
            fi
            
            echo ""
            
            # Step 3: Health check
            echo "Running post-deployment health check..."
            monitor_umbrella_health "basic"
            
            echo ""
            echo "🎉 Cisco Umbrella deployment completed!"
            echo "Next steps:"
            echo "1. Install Cisco Umbrella PKG file via JAMF or manual installation"
            echo "2. Verify client is running and connected"
            echo "3. Test DNS filtering and security features"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Enterprise Cisco Umbrella Roaming Client Management"
            echo ""
            echo "Usage: $0 <action> [options]"
            echo ""
            echo "Actions:"
            echo "  configure [profile]                         - Generate Umbrella configuration"
            echo "  install-certs [source]                      - Install Cisco certificates"
            echo "  health [type]                               - Monitor Umbrella health"
            echo "  report [type]                               - Generate deployment reports"
            echo "  set-params <fingerprint> <org_id> <user_id> - Set organization parameters"
            echo "  deploy [profile]                            - Full deployment workflow"
            echo "  help                                        - Show this help message"
            echo ""
            echo "User Profiles:"
            echo "  executive   - High security, minimal blocking"
            echo "  standard    - Balanced security and usability (default)"
            echo "  guest       - Basic security, extensive blocking"
            echo "  developer   - Medium security, minimal blocking"
            echo "  kiosk       - Maximum security, extensive blocking"
            echo ""
            echo "Certificate Sources:"
            echo "  auto        - Download from Cisco (default)"
            echo "  local       - Use certificates in $CERTS_DIR"
            echo "  <file>      - Specific certificate file"
            echo ""
            echo "Health Check Types:"
            echo "  basic       - Basic connectivity and configuration checks"
            echo "  comprehensive - Extended monitoring and diagnostics"
            echo ""
            echo "Report Types:"
            echo "  summary     - Deployment overview (default)"
            echo "  security    - Security configuration analysis"
            echo "  audit       - Audit trail and events"
            echo ""
            echo "Features:"
            echo "  • Automated Cisco Umbrella client deployment"
            echo "  • Profile-based security configuration"
            echo "  • Enterprise certificate management"
            echo "  • Real-time health monitoring and diagnostics"
            echo "  • Comprehensive audit logging and compliance"
            echo "  • Integration with Roundfleet security infrastructure"
            echo "  • Advanced threat protection and DNS filtering"
            ;;
    esac
}

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

Quick Reference Commands

Initial Setup

# Set organization parameters (obtained from Cisco dashboard)
./umbrella_manager.sh set-params "your_api_fingerprint" "your_org_id" "your_user_id"

# Deploy with standard profile
./umbrella_manager.sh deploy standard

# Deploy with executive profile
./umbrella_manager.sh deploy executive

Configuration Management

# Generate configuration for different user profiles
./umbrella_manager.sh configure standard
./umbrella_manager.sh configure executive
./umbrella_manager.sh configure guest
./umbrella_manager.sh configure developer
./umbrella_manager.sh configure kiosk

Certificate Management

# Install certificates automatically
./umbrella_manager.sh install-certs auto

# Install from local directory
./umbrella_manager.sh install-certs local

# Install specific certificate file
./umbrella_manager.sh install-certs /path/to/cisco_cert.pem

Health Monitoring

# Basic health check
./umbrella_manager.sh health

# Comprehensive health check
./umbrella_manager.sh health comprehensive

Reporting Operations

# Generate summary report
./umbrella_manager.sh report

# Generate security assessment
./umbrella_manager.sh report security

# Generate audit report
./umbrella_manager.sh report audit

Integration Examples

JAMF Pro Integration

#!/bin/bash

# JAMF Pro script for Cisco Umbrella deployment
# Parameters: $4 = user_profile, $5 = api_fingerprint, $6 = api_org_id, $7 = api_user_id

USER_PROFILE="$4"
API_FINGERPRINT="$5"
API_ORG_ID="$6"
API_USER_ID="$7"

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

# Set organization parameters
/usr/local/bin/roundfleet_umbrella_manager.sh set-params \
    "$API_FINGERPRINT" "$API_ORG_ID" "$API_USER_ID"

# Deploy Umbrella configuration
/usr/local/bin/roundfleet_umbrella_manager.sh deploy "$USER_PROFILE"

# Report status back to JAMF
if [[ $? -eq 0 ]]; then
    echo "Cisco Umbrella deployed successfully"
    exit 0
else
    echo "Cisco Umbrella deployment failed"
    exit 1
fi

Security Monitoring Integration

#!/bin/bash

# Continuous monitoring script for Cisco Umbrella
monitor_umbrella_continuous() {
    local monitoring_interval=300  # 5 minutes
    local alert_threshold=3
    local consecutive_failures=0
    
    while true; do
        # Run health check
        if /usr/local/bin/roundfleet_umbrella_manager.sh health basic &>/dev/null; then
            consecutive_failures=0
            echo "$(date): Umbrella health check passed"
        else
            consecutive_failures=$((consecutive_failures + 1))
            echo "$(date): Umbrella health check failed ($consecutive_failures)"
            
            # Alert after consecutive failures
            if [[ $consecutive_failures -ge $alert_threshold ]]; then
                send_security_alert "Cisco Umbrella service degraded" "CRITICAL"
                consecutive_failures=0
            fi
        fi
        
        sleep "$monitoring_interval"
    done
}

Advanced Security Features

Threat Intelligence Integration

# Enhanced security monitoring with threat intelligence
enhanced_threat_monitoring() {
    local threat_feeds=("malware" "phishing" "botnet" "ransomware")
    
    echo "=== Advanced Threat Monitoring ==="
    
    for feed in "${threat_feeds[@]}"; do
        local blocked_count=$(grep -c "$feed" /Library/Logs/OpenDNSRoamingClient.log 2>/dev/null || echo 0)
        echo "$feed threats blocked: $blocked_count"
        
        if [[ $blocked_count -gt 100 ]]; then
            log_security_event "HIGH_THREAT_ACTIVITY" "feed=$feed,count=$blocked_count" "WARNING"
        fi
    done
}

Policy Automation

# Automated policy updates based on security events
automated_policy_updates() {
    local threat_level="$1"
    
    case "$threat_level" in
        "high")
            # Enable maximum security
            UMBRELLA_CONFIG_PARAMS["BlockAdware"]="true"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            UMBRELLA_CONFIG_PARAMS["SafeSearch"]="true"
            generate_umbrella_config "kiosk"
            ;;
        "medium")
            # Standard security
            generate_umbrella_config "standard"
            ;;
        "low")
            # Reduced security for business needs
            generate_umbrella_config "executive"
            ;;
    esac
    
    # Restart Umbrella client to apply changes
    sudo launchctl unload /Library/LaunchDaemons/com.opendns.osx.RoamingClientConfigUpdater.plist 2>/dev/null
    sudo launchctl load /Library/LaunchDaemons/com.opendns.osx.RoamingClientConfigUpdater.plist 2>/dev/null
}

Best Practices

  1. Secure API credentials and use environment variables for sensitive data
  2. Implement profile-based configurations for different user types
  3. Enable comprehensive logging for security monitoring and compliance
  4. Automate certificate management and renewal processes
  5. Monitor service health continuously with alerting
  6. Integrate with SIEM systems for centralized security monitoring
  7. Regular policy updates based on threat intelligence
  8. Test DNS filtering and security features after deployment

This enterprise Cisco Umbrella management system provides comprehensive security DNS protection with automated deployment, monitoring capabilities, and enterprise-grade controls for effective Roundfleet security management.

Chrome Extension Management and Security on macOS

Manage and secure Google Chrome extensions across your Roundfleet devices with comprehensive discovery, analysis, and policy enforcement tools. This tutorial covers extension enumeration, security assessment, and enterprise browser management.

Understanding Chrome Extension Management

Chrome extensions enhance browser functionality but can introduce security risks. Enterprise management includes:

  • Extension Discovery - Identify all installed extensions across devices
  • Security Analysis - Assess extension permissions and risks
  • Policy Enforcement - Control which extensions are allowed
  • Compliance Monitoring - Ensure adherence to security policies

Extension Security Concerns

Browser extensions can pose enterprise security risks:

  • Data Access - Extensions can read browsing data and personal information
  • Network Requests - Some extensions communicate with external servers
  • Malicious Extensions - Unauthorized or compromised extensions
  • Productivity Impact - Non-business extensions affecting work efficiency
  • Compliance Violations - Extensions that conflict with regulatory requirements

Basic Chrome Extension Discovery

List All Installed Extensions

#!/bin/bash

# Basic Chrome extension listing
currentUser=$(ls -l /dev/console | awk '{print $3}')
ext_dir="/Users/$currentUser/Library/Application Support/Google/Chrome/Default/Extensions/"

echo "Chrome extensions for user: $currentUser"
echo "======================================="

for i in $(find "$ext_dir" -name 'manifest.json'); do
    extension_id=$(basename "$(dirname "$(dirname "$i")")")
    echo "$extension_id"
done

Enhanced Extension Discovery with Details

#!/bin/bash

# Enhanced Chrome extension discovery with metadata
discover_chrome_extensions() {
    local user_name="${1:-$(ls -l /dev/console | awk '{print $3}')}"
    local detailed="${2:-false}"
    
    local chrome_dir="/Users/$user_name/Library/Application Support/Google/Chrome"
    local extensions_dir="$chrome_dir/Default/Extensions"
    
    if [[ ! -d "$extensions_dir" ]]; then
        echo "Chrome extensions directory not found for user: $user_name"
        return 1
    fi
    
    echo "=== Chrome Extension Discovery ==="
    echo "User: $user_name"
    echo "Extensions Directory: $extensions_dir"
    echo "Discovery Date: $(date)"
    echo ""
    
    local extension_count=0
    local extensions_found=()
    
    # Find all manifest.json files
    while IFS= read -r -d '' manifest_path; do
        ((extension_count++))
        
        local extension_id=$(basename "$(dirname "$(dirname "$manifest_path")")")
        local version_dir=$(dirname "$manifest_path")
        local version=$(basename "$version_dir")
        
        extensions_found+=("$extension_id:$version:$manifest_path")
        
        if [[ "$detailed" == "true" ]]; then
            echo "--- Extension $extension_count ---"
            echo "ID: $extension_id"
            echo "Version: $version"
            echo "Manifest: $manifest_path"
            
            # Extract extension name and description from manifest
            if [[ -f "$manifest_path" ]]; then
                local name=$(python3 -c "import json, sys; data=json.load(open('$manifest_path')); print(data.get('name', 'Unknown'))" 2>/dev/null || echo "Unknown")
                local description=$(python3 -c "import json, sys; data=json.load(open('$manifest_path')); print(data.get('description', 'No description'))" 2>/dev/null || echo "No description")
                
                echo "Name: $name"
                echo "Description: $description"
            fi
            echo ""
        else
            echo "$extension_id"
        fi
        
    done < <(find "$extensions_dir" -name 'manifest.json' -print0 2>/dev/null)
    
    echo ""
    echo "Total extensions found: $extension_count"
    
    return 0
}

# Usage examples
discover_chrome_extensions "$(whoami)" "true"
discover_chrome_extensions "$(whoami)" "false"

Check Specific Extension Installation

#!/bin/bash

# Check if specific extension is installed
check_extension_installed() {
    local extension_id="$1"
    local user_name="${2:-$(ls -l /dev/console | cut -d " " -f 4)}"
    
    if [[ -z "$extension_id" ]]; then
        echo "Usage: check_extension_installed <extension_id> [username]"
        echo "Example: check_extension_installed nmmhkkegccagdldgiimedpiccmgmieda"
        return 1
    fi
    
    local extension_path="/Users/$user_name/Library/Application Support/Google/Chrome/Default/Extensions/$extension_id"
    
    if [[ -d "$extension_path" ]]; then
        echo "<result>The extension $extension_id is installed.</result>"
        
        # Get extension details if manifest exists
        local manifest_files=("$extension_path"/*/manifest.json)
        if [[ -f "${manifest_files[0]}" ]]; then
            local manifest_path="${manifest_files[0]}"
            local version=$(basename "$(dirname "$manifest_path")")
            
            echo "Extension Details:"
            echo "- ID: $extension_id"
            echo "- Version: $version"
            echo "- Path: $extension_path"
            
            # Extract name from manifest
            local name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Unknown'))" 2>/dev/null || echo "Unknown")
            echo "- Name: $name"
        fi
        
        return 0
    else
        echo "<result>Extension $extension_id is not installed.</result>"
        return 1
    fi
}

# Example usage
check_extension_installed "nmmhkkegccagdldgiimedpiccmgmieda"
check_extension_installed "cjpalhdlnbpafiamejdnhcphjbkeiagm"

Advanced Extension Analysis

Comprehensive Extension Security Analysis

#!/bin/bash

# Comprehensive Chrome extension security analysis
analyze_extension_security() {
    local extension_id="$1"
    local user_name="${2:-$(ls -l /dev/console | awk '{print $3}')}"
    
    if [[ -z "$extension_id" ]]; then
        echo "Usage: analyze_extension_security <extension_id> [username]"
        return 1
    fi
    
    local extension_path="/Users/$user_name/Library/Application Support/Google/Chrome/Default/Extensions/$extension_id"
    
    if [[ ! -d "$extension_path" ]]; then
        echo "Extension $extension_id not found for user $user_name"
        return 1
    fi
    
    echo "=== Extension Security Analysis ==="
    echo "Extension ID: $extension_id"
    echo "User: $user_name"
    echo "Analysis Date: $(date)"
    echo ""
    
    # Find the manifest file
    local manifest_files=("$extension_path"/*/manifest.json)
    if [[ ! -f "${manifest_files[0]}" ]]; then
        echo "Manifest file not found for extension $extension_id"
        return 1
    fi
    
    local manifest_path="${manifest_files[0]}"
    local version_dir=$(dirname "$manifest_path")
    local version=$(basename "$version_dir")
    
    echo "--- Basic Information ---"
    echo "Version: $version"
    echo "Install Path: $extension_path"
    echo "Manifest: $manifest_path"
    
    # Parse manifest for security analysis
    if command -v python3 >/dev/null 2>&1; then
        echo ""
        echo "--- Extension Metadata ---"
        
        # Extract basic information
        local name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Unknown'))" 2>/dev/null || echo "Unknown")
        local description=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('description', 'No description'))" 2>/dev/null || echo "No description")
        local manifest_version=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('manifest_version', 'Unknown'))" 2>/dev/null || echo "Unknown")
        
        echo "Name: $name"
        echo "Description: $description"
        echo "Manifest Version: $manifest_version"
        
        # Security analysis
        echo ""
        echo "--- Security Analysis ---"
        
        # Check permissions
        local permissions=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    perms = data.get('permissions', [])
    for perm in perms:
        print(f'  - {perm}')
except:
    print('  - Error reading permissions')
" 2>/dev/null)
        
        if [[ -n "$permissions" ]]; then
            echo "Permissions:"
            echo "$permissions"
        else
            echo "Permissions: None declared"
        fi
        
        # Check host permissions
        local host_permissions=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    hosts = data.get('host_permissions', [])
    if not hosts:
        hosts = data.get('permissions', [])
        hosts = [h for h in hosts if h.startswith('http') or '*' in h]
    for host in hosts:
        print(f'  - {host}')
except:
    print('  - Error reading host permissions')
" 2>/dev/null)
        
        if [[ -n "$host_permissions" ]]; then
            echo "Host Permissions:"
            echo "$host_permissions"
        else
            echo "Host Permissions: None declared"
        fi
        
        # Check content scripts
        local content_scripts=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    scripts = data.get('content_scripts', [])
    if scripts:
        print('Content scripts detected:')
        for i, script in enumerate(scripts):
            matches = script.get('matches', [])
            print(f'  Script {i+1}: {matches}')
    else:
        print('No content scripts')
except:
    print('Error reading content scripts')
" 2>/dev/null)
        
        echo "Content Scripts: $content_scripts"
        
        # Risk assessment
        echo ""
        echo "--- Risk Assessment ---"
        assess_extension_risk "$manifest_path"
        
    else
        echo "Python3 not available - limited analysis"
    fi
    
    # File analysis
    echo ""
    echo "--- File Analysis ---"
    local file_count=$(find "$version_dir" -type f | wc -l)
    local total_size=$(du -sh "$version_dir" | cut -f1)
    
    echo "Total Files: $file_count"
    echo "Total Size: $total_size"
    
    # Check for suspicious files
    local js_files=$(find "$version_dir" -name "*.js" | wc -l)
    local html_files=$(find "$version_dir" -name "*.html" | wc -l)
    local json_files=$(find "$version_dir" -name "*.json" | wc -l)
    
    echo "JavaScript Files: $js_files"
    echo "HTML Files: $html_files"
    echo "JSON Files: $json_files"
    
    echo ""
    echo "=== Analysis Complete ==="
}

# Risk assessment function
assess_extension_risk() {
    local manifest_path="$1"
    local risk_score=0
    local risk_factors=()
    
    # Check for high-risk permissions
    local high_risk_perms=$(python3 -c "
import json
high_risk = ['activeTab', 'tabs', 'storage', 'cookies', 'history', 'bookmarks', 'downloads', 'management', 'nativeMessaging', 'proxy', 'webRequest', 'webRequestBlocking']
try:
    data = json.load(open('$manifest_path'))
    perms = data.get('permissions', [])
    host_perms = data.get('host_permissions', [])
    all_perms = perms + host_perms
    
    found_high_risk = []
    for perm in all_perms:
        if perm in high_risk:
            found_high_risk.append(perm)
        elif perm == '<all_urls>' or perm == '*://*/*':
            found_high_risk.append('all_urls')
    
    print(','.join(found_high_risk))
except:
    pass
" 2>/dev/null)
    
    if [[ -n "$high_risk_perms" ]]; then
        IFS=',' read -ra PERMS <<< "$high_risk_perms"
        for perm in "${PERMS[@]}"; do
            case "$perm" in
                "all_urls"|"*://*/*")
                    risk_score=$((risk_score + 30))
                    risk_factors+=("Access to all websites")
                    ;;
                "tabs"|"activeTab")
                    risk_score=$((risk_score + 20))
                    risk_factors+=("Can access browser tabs")
                    ;;
                "storage"|"cookies")
                    risk_score=$((risk_score + 15))
                    risk_factors+=("Can access stored data")
                    ;;
                "webRequest"|"webRequestBlocking")
                    risk_score=$((risk_score + 25))
                    risk_factors+=("Can intercept web requests")
                    ;;
                "nativeMessaging")
                    risk_score=$((risk_score + 20))
                    risk_factors+=("Can communicate with native applications")
                    ;;
                *)
                    risk_score=$((risk_score + 10))
                    risk_factors+=("Has $perm permission")
                    ;;
            esac
        done
    fi
    
    # Determine risk level
    local risk_level
    if [[ $risk_score -ge 50 ]]; then
        risk_level="HIGH"
    elif [[ $risk_score -ge 25 ]]; then
        risk_level="MEDIUM"
    elif [[ $risk_score -ge 10 ]]; then
        risk_level="LOW"
    else
        risk_level="MINIMAL"
    fi
    
    echo "Risk Level: $risk_level (Score: $risk_score)"
    
    if [[ ${#risk_factors[@]} -gt 0 ]]; then
        echo "Risk Factors:"
        for factor in "${risk_factors[@]}"; do
            echo "  ⚠️ $factor"
        done
    else
        echo "✓ No significant risk factors identified"
    fi
}

# Usage
analyze_extension_security "nmmhkkegccagdldgiimedpiccmgmieda"

Enterprise Chrome Extension Management System

#!/bin/bash

# Roundfleet Chrome Extension Management Tool
# Comprehensive browser extension discovery, analysis, and policy enforcement

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_chrome_extensions.log"
REPORT_DIR="/etc/roundfleet/reports/chrome_extensions"
CONFIG_DIR="/etc/roundfleet/chrome_extensions"
POLICY_DIR="/etc/roundfleet/policies/chrome_extensions"
ALLOWLIST_FILE="$CONFIG_DIR/allowed_extensions.json"
BLOCKLIST_FILE="$CONFIG_DIR/blocked_extensions.json"

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

# Extension policy templates
declare -A EXTENSION_POLICIES=(
    ["enterprise_strict"]="allowlist_only,no_developer_mode,approved_store_only,security_review_required"
    ["healthcare"]="hipaa_compliant_only,no_data_access,approved_medical_only,audit_required"
    ["financial"]="sox_compliant,no_financial_data_access,bank_approved_only,strict_monitoring"
    ["education"]="educational_approved,student_safe,no_social_media,content_filtered"
    ["development"]="dev_tools_allowed,github_integration,productivity_focus,moderate_restrictions"
    ["general_business"]="productivity_focus,no_games,security_validated,business_approved"
    ["kiosk_lockdown"]="no_extensions,system_locked,maximum_security,zero_customization"
    ["government"]="security_cleared,no_external_communication,audit_trail,maximum_security"
    ["retail"]="pos_safe,no_personal_use,business_hours_only,transaction_secure"
    ["manufacturing"]="industrial_approved,no_social_access,production_safe,minimal_permissions"
)

# Known security risk extensions
declare -A RISKY_EXTENSIONS=(
    ["adware"]="AdBlock variants with suspicious permissions,Free VPN extensions,Coupon extensions"
    ["privacy_risk"]="Extensions requesting all_urls,Password managers from unknown developers,Extensions with native messaging"
    ["productivity_risk"]="Social media extensions,Gaming extensions,Streaming video extensions"
    ["security_risk"]="Extensions from unknown developers,Extensions with webRequest permissions,Proxy extensions"
)

# Trusted extension developers
declare -A TRUSTED_DEVELOPERS=(
    ["google"]="Google LLC,Chrome Web Store official"
    ["microsoft"]="Microsoft Corporation"
    ["adobe"]="Adobe Inc."
    ["1password"]="AgileBits Inc."
    ["lastpass"]="LogMeIn, Inc."
    ["ublock"]="Raymond Hill (gorhill)"
    ["grammarly"]="Grammarly Inc."
    ["zoom"]="Zoom Video Communications, Inc."
)

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

# Discover all Chrome extensions across all users
discover_fleet_extensions() {
    local scan_all_users="${1:-false}"
    local output_format="${2:-detailed}"
    local security_analysis="${3:-true}"
    
    log_action "Starting fleet-wide Chrome extension discovery"
    
    echo "=== Roundfleet Chrome Extension Discovery ==="
    echo "Scan All Users: $scan_all_users"
    echo "Output Format: $output_format"
    echo "Security Analysis: $security_analysis"
    echo ""
    
    local total_extensions=0
    local total_users=0
    local high_risk_extensions=0
    local unknown_extensions=0
    local fleet_data=()
    
    # Determine users to scan
    local users_to_scan=()
    if [[ "$scan_all_users" == "true" ]]; then
        # Get all users with home directories
        while IFS= read -r user_dir; do
            local username=$(basename "$user_dir")
            users_to_scan+=("$username")
        done < <(find /Users -maxdepth 1 -type d -not -name "Shared" -not -name "." -not -name ".." | grep -v "/Users$")
    else
        # Current console user only
        local current_user=$(ls -l /dev/console | awk '{print $3}')
        users_to_scan=("$current_user")
    fi
    
    # Scan each user
    for username in "${users_to_scan[@]}"; do
        local chrome_dir="/Users/$username/Library/Application Support/Google/Chrome"
        local extensions_dir="$chrome_dir/Default/Extensions"
        
        if [[ ! -d "$extensions_dir" ]]; then
            continue
        fi
        
        ((total_users++))
        echo "--- User: $username ---"
        
        local user_extension_count=0
        
        # Find all extensions for this user
        while IFS= read -r -d '' manifest_path; do
            ((total_extensions++))
            ((user_extension_count++))
            
            local extension_id=$(basename "$(dirname "$(dirname "$manifest_path")")")
            local version_dir=$(dirname "$manifest_path")
            local version=$(basename "$version_dir")
            
            # Basic extension info
            local name="Unknown"
            local description="No description"
            local risk_level="UNKNOWN"
            
            if command -v python3 >/dev/null 2>&1; then
                name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Unknown'))" 2>/dev/null || echo "Unknown")
                description=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('description', 'No description'))" 2>/dev/null || echo "No description")
                
                if [[ "$security_analysis" == "true" ]]; then
                    risk_level=$(assess_extension_risk_level "$manifest_path")
                    if [[ "$risk_level" == "HIGH" ]]; then
                        ((high_risk_extensions++))
                    fi
                fi
            fi
            
            # Check if extension is known/trusted
            local trust_status="UNKNOWN"
            check_extension_trust "$extension_id" "$name" trust_status
            
            if [[ "$trust_status" == "UNKNOWN" ]]; then
                ((unknown_extensions++))
            fi
            
            # Store data for reporting
            fleet_data+=("$username|$extension_id|$name|$version|$risk_level|$trust_status|$description")
            
            # Output based on format
            case "$output_format" in
                "detailed")
                    echo "  Extension: $name"
                    echo "    ID: $extension_id"
                    echo "    Version: $version"
                    echo "    Risk: $risk_level"
                    echo "    Trust: $trust_status"
                    echo ""
                    ;;
                "summary")
                    echo "  $extension_id ($name) - Risk: $risk_level"
                    ;;
                "ids_only")
                    echo "  $extension_id"
                    ;;
            esac
            
        done < <(find "$extensions_dir" -name 'manifest.json' -print0 2>/dev/null)
        
        echo "  User Extensions: $user_extension_count"
        echo ""
    done
    
    # Generate summary
    echo "=== Fleet Discovery Summary ==="
    echo "Total Users Scanned: $total_users"
    echo "Total Extensions Found: $total_extensions"
    echo "High Risk Extensions: $high_risk_extensions"
    echo "Unknown Extensions: $unknown_extensions"
    echo ""
    
    # Generate reports
    if [[ "$output_format" == "json" ]]; then
        generate_json_fleet_report fleet_data
    elif [[ "$output_format" == "csv" ]]; then
        generate_csv_fleet_report fleet_data
    fi
    
    log_action "Fleet extension discovery completed: $total_extensions extensions found across $total_users users"
}

# Assess extension risk level
assess_extension_risk_level() {
    local manifest_path="$1"
    local risk_score=0
    
    # Use Python to analyze manifest
    risk_score=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    score = 0
    
    # Check permissions
    perms = data.get('permissions', []) + data.get('host_permissions', [])
    
    for perm in perms:
        if perm in ['<all_urls>', '*://*/*']:
            score += 30
        elif perm in ['tabs', 'activeTab']:
            score += 20
        elif perm in ['webRequest', 'webRequestBlocking']:
            score += 25
        elif perm in ['storage', 'cookies', 'history']:
            score += 15
        elif perm in ['nativeMessaging']:
            score += 20
        elif perm.startswith('http'):
            score += 5
    
    print(score)
except:
    print(0)
" 2>/dev/null || echo "0")
    
    if [[ $risk_score -ge 50 ]]; then
        echo "HIGH"
    elif [[ $risk_score -ge 25 ]]; then
        echo "MEDIUM"
    elif [[ $risk_score -ge 10 ]]; then
        echo "LOW"
    else
        echo "MINIMAL"
    fi
}

# Check extension trust status
check_extension_trust() {
    local extension_id="$1"
    local extension_name="$2"
    local -n trust_ref=$3
    
    # Check against allowlist
    if [[ -f "$ALLOWLIST_FILE" ]]; then
        if grep -q "$extension_id" "$ALLOWLIST_FILE" 2>/dev/null; then
            trust_ref="APPROVED"
            return
        fi
    fi
    
    # Check against blocklist
    if [[ -f "$BLOCKLIST_FILE" ]]; then
        if grep -q "$extension_id" "$BLOCKLIST_FILE" 2>/dev/null; then
            trust_ref="BLOCKED"
            return
        fi
    fi
    
    # Check against known good extensions (simplified)
    case "$extension_id" in
        "cjpalhdlnbpafiamejdnhcphjbkeiagm") # uBlock Origin
            trust_ref="TRUSTED"
            ;;
        "nmmhkkegccagdldgiimedpiccmgmieda") # Google Translate
            trust_ref="TRUSTED"
            ;;
        "gighmmpiobklfepjocnamgkkbiglidom") # AdBlock
            trust_ref="TRUSTED"
            ;;
        *)
            trust_ref="UNKNOWN"
            ;;
    esac
}

# Generate JSON fleet report
generate_json_fleet_report() {
    local -n data_ref=$1
    local report_file="$REPORT_DIR/fleet_extensions_$(date +%Y%m%d_%H%M%S).json"
    
    cat > "$report_file" << EOF
{
    "chrome_extension_fleet_report": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION",
        "extensions": [
EOF
    
    local first=true
    for data_line in "${data_ref[@]}"; do
        IFS='|' read -r username extension_id name version risk_level trust_status description <<< "$data_line"
        
        if [[ "$first" == "true" ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        
        cat >> "$report_file" << EOF
            {
                "user": "$username",
                "extension_id": "$extension_id",
                "name": "$name",
                "version": "$version",
                "risk_level": "$risk_level",
                "trust_status": "$trust_status",
                "description": "$description"
            }
EOF
    done
    
    cat >> "$report_file" << EOF

        ]
    }
}
EOF
    
    echo "JSON report generated: $report_file"
}

# Enforce extension policies
enforce_extension_policy() {
    local policy_name="$1"
    local action="${2:-report}"
    local target_user="${3:-all}"
    
    echo "=== Enforcing Extension Policy: $policy_name ==="
    echo "Action: $action"
    echo "Target User: $target_user"
    echo ""
    
    if [[ -z "${EXTENSION_POLICIES[$policy_name]}" ]]; then
        echo "Error: Unknown policy '$policy_name'"
        echo "Available policies: ${!EXTENSION_POLICIES[*]}"
        return 1
    fi
    
    local policy_rules="${EXTENSION_POLICIES[$policy_name]}"
    echo "Policy Rules: $policy_rules"
    echo ""
    
    local violations=()
    local compliant_extensions=()
    
    # Implement policy enforcement logic based on policy type
    case "$policy_name" in
        "enterprise_strict")
            enforce_strict_policy violations compliant_extensions "$target_user"
            ;;
        "healthcare")
            enforce_healthcare_policy violations compliant_extensions "$target_user"
            ;;
        "kiosk_lockdown")
            enforce_kiosk_policy violations compliant_extensions "$target_user"
            ;;
        *)
            enforce_general_policy "$policy_name" violations compliant_extensions "$target_user"
            ;;
    esac
    
    # Report results
    echo "Policy Enforcement Results:"
    echo "Compliant Extensions: ${#compliant_extensions[@]}"
    echo "Policy Violations: ${#violations[@]}"
    
    if [[ ${#violations[@]} -gt 0 ]]; then
        echo ""
        echo "Violations Found:"
        for violation in "${violations[@]}"; do
            echo "  ⚠️ $violation"
        done
    fi
    
    # Take action
    case "$action" in
        "report")
            echo ""
            echo "Action: Report Only - No changes made"
            ;;
        "disable")
            echo ""
            echo "Action: Disable violating extensions"
            disable_violating_extensions violations
            ;;
        "remove")
            echo ""
            echo "Action: Remove violating extensions"
            remove_violating_extensions violations
            ;;
    esac
    
    log_action "Extension policy enforcement completed: $policy_name"
}

# Main execution function
main() {
    local action="${1:-help}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Roundfleet Chrome Extension Management Started ==="
    log_action "Action: $action"
    
    case "$action" in
        "discover")
            discover_chrome_extensions "${param1:-$(whoami)}" "${param2:-true}"
            ;;
        "check")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 check <extension_id> [username]"
                exit 1
            fi
            check_extension_installed "$param1" "$param2"
            ;;
        "analyze")
            if [[ -z "$param1" ]]; then
                echo "Usage: $0 analyze <extension_id> [username]"
                exit 1
            fi
            analyze_extension_security "$param1" "$param2"
            ;;
        "fleet")
            discover_fleet_extensions "${param1:-false}" "${param2:-detailed}" "${param3:-true}"
            ;;
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Available policies: ${!EXTENSION_POLICIES[*]}"
                exit 1
            fi
            enforce_extension_policy "$param1" "${param2:-report}" "${param3:-all}"
            ;;
        "help")
            echo "Usage: $0 [action] [options...]"
            echo "Actions:"
            echo "  discover [username] [detailed] - Discover extensions for user"
            echo "  check <extension_id> [username] - Check if extension is installed"
            echo "  analyze <extension_id> [username] - Analyze extension security"
            echo "  fleet [all_users] [format] [security] - Fleet-wide discovery"
            echo "  policy <policy_name> [action] [user] - Enforce extension policy"
            echo "  help - Show this help"
            echo ""
            echo "Policies: ${!EXTENSION_POLICIES[*]}"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
    
    log_action "=== Chrome extension management completed ==="
}

# Execute main function
main "$@"

Important Notes

  • Extension IDs are 32-character strings uniquely identifying each extension
  • Manifest files contain extension metadata and permission requirements
  • Security analysis should focus on permissions and data access
  • Enterprise policies should balance functionality with security requirements
  • Regular monitoring helps detect unauthorized or risky extensions
  • User training is essential for extension security awareness

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 "=== Roundfleet 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 "🏢 Roundfleet 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 Roundfleet

  1. Specify the application path in the script
  2. Choose between detailed analysis or quick validation
  3. Deploy through Roundfleet'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 Roundfleet 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

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

# Configuration
LOG_FILE="/var/log/roundfleet_certificates.log"
BACKUP_DIR="/var/backups/certificates"
CERT_STORE_DIR="/Library/Keychains"
TEMP_DIR="/tmp/roundfleet_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 "=== Roundfleet 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/roundfleet_cert_renewal.sh"
    local launchd_plist="/Library/LaunchDaemons/com.roundfleet.cert.renewal.plist"
    
    # Create renewal script
    cat > "$renewal_script" << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/roundfleet_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.roundfleet.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 Roundfleet 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

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

# Configuration
LOG_FILE="/var/log/roundfleet_cache.log"
BACKUP_DIR="/var/backups/roundfleet/cache"
REPORT_DIR="/var/reports/roundfleet/cache"
CONFIG_FILE="/etc/roundfleet/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 "Roundfleet 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.roundfleet.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.roundfleet.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 "=== Roundfleet 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 "Roundfleet 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 "=== Roundfleet 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