Tutorial

New updates and improvements to Macfleet.

Configure Trackpad Settings on macOS

Managing trackpad settings across your MacFleet 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 MacFleet
# 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 MacFleet 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

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

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_codesigning.log"
REPORT_DIR="/etc/macfleet/reports/codesigning"
CONFIG_DIR="/etc/macfleet/codesigning"
POLICY_DIR="/etc/macfleet/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 "=== MacFleet 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 MacFleet 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

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

# Configuration
CONFIG_FILE="/etc/macfleet/clipboard_policy.conf"
LOG_FILE="/var/log/macfleet_clipboard.log"
CACHE_DIR="/Library/MacFleet/Clipboard"
AUDIT_LOG="/var/log/macfleet_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
# MacFleet 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/MacFleet/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 "=== MacFleet 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 "MacFleet 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: help@company.com | 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 security@company.com"
    
    # Emergency contact
    manage_content_templates "create" "emergency_contact" "Emergency IT Support: +1-555-HELP (4357) | Available 24/7 | Incident Report: security@company.com"
}

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
MacFleet 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 MacFleet.

Cisco Umbrella Roaming Client Management on macOS

Deploy and manage Cisco Umbrella roaming clients across your MacFleet 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

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

# Configuration
SCRIPT_NAME="MacFleet Cisco Umbrella Manager"
VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_umbrella.log"
AUDIT_LOG="/var/log/macfleet_umbrella_audit.log"
CONFIG_DIR="/Library/Application Support/OpenDNS Roaming Client"
UMBRELLA_CONFIG="$CONFIG_DIR/OrgInfo.plist"
CERTS_DIR="/etc/macfleet/umbrella/certificates"
POLICIES_DIR="/etc/macfleet/umbrella/policies"
TEMP_DIR="/tmp/macfleet_umbrella"
BACKUP_DIR="/var/backups/umbrella"
MONITORING_INTERVAL=300  # 5 minutes
HEALTH_CHECK_TIMEOUT=30
ORGANIZATION_NAME="MacFleet 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 "MacFleet 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 MacFleet 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/macfleet_umbrella_manager.sh" ]]; then
    curl -o "/usr/local/bin/macfleet_umbrella_manager.sh" \
         "https://scripts.macfleet.com/umbrella_manager.sh"
    chmod +x "/usr/local/bin/macfleet_umbrella_manager.sh"
fi

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

# Deploy Umbrella configuration
/usr/local/bin/macfleet_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/macfleet_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 MacFleet security management.

Chrome Extension Management and Security on macOS

Manage and secure Google Chrome extensions across your MacFleet 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

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

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_chrome_extensions.log"
REPORT_DIR="/etc/macfleet/reports/chrome_extensions"
CONFIG_DIR="/etc/macfleet/chrome_extensions"
POLICY_DIR="/etc/macfleet/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 "=== MacFleet 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 "=== MacFleet 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