Tutorial

New updates and improvements to Macfleet.

AirDrop Management on macOS

Control AirDrop functionality on your MacFleet devices to enhance security and prevent unauthorized file transfers. This tutorial covers enabling, disabling, monitoring, and managing AirDrop settings for corporate compliance and data protection.

Understanding AirDrop on macOS

AirDrop is Apple's wireless file sharing technology that allows users to transfer files between nearby Apple devices including:

  • Mac computers running macOS Lion (10.7) or later
  • iOS devices (iPhone, iPad, iPod touch) with iOS 7 or later
  • Apple Watch for supported content types

Security Considerations

In enterprise environments, AirDrop can pose security risks:

  • Data leakage through unauthorized file transfers
  • Malware distribution via infected files
  • Corporate policy violations through uncontrolled sharing
  • Network security bypassing traditional file transfer controls

Basic AirDrop Control Commands

Disable AirDrop Functionality

#!/bin/sh

# Disable AirDrop by shutting down AWDL interface
sudo ifconfig awdl0 down

echo "AirDrop functionality disabled"

Enable AirDrop Functionality

#!/bin/sh

# Enable AirDrop by bringing up AWDL interface
sudo ifconfig awdl0 up

echo "AirDrop functionality enabled"

Check AirDrop Status

#!/bin/bash

# Check current AirDrop/AWDL interface status
check_airdrop_status() {
    local awdl_status
    awdl_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
    
    if [[ "$awdl_status" == "active" ]]; then
        echo "AirDrop: ENABLED"
        return 0
    elif [[ "$awdl_status" == "inactive" ]]; then
        echo "AirDrop: DISABLED"
        return 1
    else
        echo "AirDrop: STATUS UNKNOWN"
        return 2
    fi
}

check_airdrop_status

Advanced AirDrop Management

Comprehensive AirDrop Control Script

#!/bin/bash

# Advanced AirDrop management with validation and logging
manage_airdrop() {
    local action="$1"
    local force="${2:-false}"
    
    # Validate admin privileges
    if [[ $EUID -ne 0 ]]; then
        echo "Error: This script requires administrator privileges"
        echo "Please run with sudo: sudo $0"
        exit 1
    fi
    
    case "$action" in
        "disable")
            echo "Disabling AirDrop functionality..."
            
            # Check current status
            local current_status
            current_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
            
            if [[ "$current_status" == "inactive" ]]; then
                echo "AirDrop is already disabled"
                return 0
            fi
            
            # Disable AWDL interface
            if ifconfig awdl0 down 2>/dev/null; then
                echo "✓ AirDrop disabled successfully"
                
                # Verify the change
                sleep 2
                local new_status
                new_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
                
                if [[ "$new_status" == "inactive" ]]; then
                    echo "✓ AirDrop status verified: DISABLED"
                    return 0
                else
                    echo "⚠ Warning: AirDrop status verification failed"
                    return 1
                fi
            else
                echo "✗ Failed to disable AirDrop"
                return 1
            fi
            ;;
        "enable")
            echo "Enabling AirDrop functionality..."
            
            # Check current status
            local current_status
            current_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
            
            if [[ "$current_status" == "active" ]]; then
                echo "AirDrop is already enabled"
                return 0
            fi
            
            # Enable AWDL interface
            if ifconfig awdl0 up 2>/dev/null; then
                echo "✓ AirDrop enabled successfully"
                
                # Verify the change
                sleep 2
                local new_status
                new_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
                
                if [[ "$new_status" == "active" ]]; then
                    echo "✓ AirDrop status verified: ENABLED"
                    return 0
                else
                    echo "⚠ Warning: AirDrop status verification failed"
                    return 1
                fi
            else
                echo "✗ Failed to enable AirDrop"
                return 1
            fi
            ;;
        "status")
            echo "Checking AirDrop status..."
            
            # Get detailed interface information
            if ifconfig awdl0 &>/dev/null; then
                local status_line
                status_line=$(ifconfig awdl0 | grep "status:")
                echo "AWDL Interface: $status_line"
                
                local flags_line
                flags_line=$(ifconfig awdl0 | head -1 | cut -d'<' -f2 | cut -d'>' -f1)
                echo "Interface Flags: $flags_line"
                
                # Check if interface is up and running
                if echo "$flags_line" | grep -q "UP"; then
                    echo "AirDrop Status: ENABLED"
                else
                    echo "AirDrop Status: DISABLED"
                fi
            else
                echo "AWDL Interface: NOT AVAILABLE"
                echo "AirDrop Status: NOT SUPPORTED"
            fi
            ;;
        *)
            echo "Usage: manage_airdrop [disable|enable|status]"
            echo "  disable - Disable AirDrop functionality"
            echo "  enable  - Enable AirDrop functionality"
            echo "  status  - Check current AirDrop status"
            return 1
            ;;
    esac
}

# Execute function with provided arguments
manage_airdrop "$@"

User-Level AirDrop Settings Management

#!/bin/bash

# Manage user-level AirDrop discovery settings
manage_airdrop_discovery() {
    local username="$1"
    local setting="$2"
    
    # Validate inputs
    if [[ -z "$username" || -z "$setting" ]]; then
        echo "Usage: manage_airdrop_discovery <username> <off|contacts|everyone>"
        return 1
    fi
    
    # Check if user exists
    if ! id "$username" &>/dev/null; then
        echo "Error: User '$username' does not exist"
        return 1
    fi
    
    # Map setting to numeric value
    local discovery_value
    case "$setting" in
        "off")
            discovery_value="0"
            ;;
        "contacts")
            discovery_value="1"
            ;;
        "everyone")
            discovery_value="2"
            ;;
        *)
            echo "Error: Invalid setting '$setting'"
            echo "Valid options: off, contacts, everyone"
            return 1
            ;;
    esac
    
    echo "Setting AirDrop discovery to '$setting' for user: $username"
    
    # Set the preference for the user
    if sudo -u "$username" defaults write com.apple.sharingd DiscoverableMode -int "$discovery_value"; then
        echo "✓ AirDrop discovery setting updated"
        
        # Restart sharing daemon to apply changes
        sudo -u "$username" killall sharingd 2>/dev/null
        
        echo "✓ Settings applied successfully"
        return 0
    else
        echo "✗ Failed to update AirDrop discovery setting"
        return 1
    fi
}

# Usage examples
manage_airdrop_discovery "$(whoami)" "contacts"

Enterprise AirDrop Policy Management

#!/bin/bash

# Enterprise AirDrop policy enforcement
apply_airdrop_policy() {
    local policy_type="$1"
    local apply_to_all_users="${2:-false}"
    
    echo "=== Applying AirDrop Policy: $policy_type ==="
    
    case "$policy_type" in
        "corporate_lockdown")
            echo "Applying corporate lockdown policy..."
            
            # Disable AirDrop system-wide
            sudo ifconfig awdl0 down
            
            # Disable for all users
            if [[ "$apply_to_all_users" == "true" ]]; then
                local users
                users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
                
                for user in $users; do
                    echo "Disabling AirDrop for user: $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 0
                done
            fi
            
            echo "✓ Corporate lockdown policy applied"
            ;;
        "contacts_only")
            echo "Applying contacts-only policy..."
            
            # Enable AirDrop but restrict to contacts
            sudo ifconfig awdl0 up
            
            if [[ "$apply_to_all_users" == "true" ]]; then
                local users
                users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
                
                for user in $users; do
                    echo "Setting contacts-only for user: $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 1
                done
            fi
            
            echo "✓ Contacts-only policy applied"
            ;;
        "unrestricted")
            echo "Applying unrestricted policy..."
            
            # Enable AirDrop with full discovery
            sudo ifconfig awdl0 up
            
            if [[ "$apply_to_all_users" == "true" ]]; then
                local users
                users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
                
                for user in $users; do
                    echo "Setting unrestricted for user: $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 2
                done
            fi
            
            echo "✓ Unrestricted policy applied"
            ;;
        *)
            echo "Error: Unknown policy type '$policy_type'"
            echo "Available policies: corporate_lockdown, contacts_only, unrestricted"
            return 1
            ;;
    esac
}

# Usage
apply_airdrop_policy "corporate_lockdown" "true"

Enterprise AirDrop Management System

#!/bin/bash

# MacFleet AirDrop Management Tool
# Comprehensive AirDrop control and monitoring for fleet devices

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_airdrop.log"
REPORT_DIR="/etc/macfleet/reports/airdrop"
CONFIG_DIR="/etc/macfleet/airdrop"
POLICY_DIR="/etc/macfleet/policies/airdrop"

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

# AirDrop policy templates
declare -A AIRDROP_POLICIES=(
    ["high_security"]="disabled,no_discovery,monitoring_enabled,audit_logging"
    ["medium_security"]="enabled,contacts_only,monitoring_enabled,audit_logging"
    ["low_security"]="enabled,everyone,monitoring_disabled,basic_logging"
    ["development"]="enabled,everyone,monitoring_enabled,debug_logging"
    ["kiosk_mode"]="disabled,no_discovery,monitoring_disabled,no_logging"
    ["guest_network"]="enabled,contacts_only,monitoring_enabled,audit_logging"
    ["executive"]="enabled,contacts_only,monitoring_enabled,executive_reporting"
    ["classroom"]="disabled,no_discovery,monitoring_enabled,educational_logging"
    ["healthcare"]="disabled,no_discovery,monitoring_enabled,hipaa_compliance"
    ["financial"]="disabled,no_discovery,monitoring_enabled,sox_compliance"
)

# Security compliance frameworks
declare -A COMPLIANCE_SETTINGS=(
    ["hipaa"]="airdrop_disabled,audit_all_attempts,data_loss_prevention"
    ["sox"]="airdrop_disabled,financial_data_protection,executive_monitoring"
    ["gdpr"]="privacy_controls,user_consent_required,data_transfer_logging"
    ["pci_dss"]="payment_data_protection,cardholder_isolation,secure_networks"
    ["iso27001"]="information_security,access_controls,incident_management"
)

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

# Advanced AirDrop status monitoring
monitor_airdrop_status() {
    local detailed="${1:-false}"
    
    log_action "Monitoring AirDrop status (detailed: $detailed)"
    
    echo "=== AirDrop Status Monitor ==="
    
    # Check AWDL interface status
    local awdl_status="unknown"
    local awdl_flags=""
    local awdl_ip=""
    
    if ifconfig awdl0 &>/dev/null; then
        awdl_status=$(ifconfig awdl0 | grep "status:" | awk '{print $2}' || echo "unknown")
        awdl_flags=$(ifconfig awdl0 | head -1 | grep -o '<.*>' | tr -d '<>')
        awdl_ip=$(ifconfig awdl0 | grep "inet " | awk '{print $2}' || echo "none")
    fi
    
    echo "AWDL Interface Status: $awdl_status"
    echo "Interface Flags: $awdl_flags"
    echo "AWDL IP Address: $awdl_ip"
    
    # Check system-wide AirDrop enablement
    local system_airdrop_enabled="false"
    if [[ "$awdl_status" == "active" ]] && echo "$awdl_flags" | grep -q "UP"; then
        system_airdrop_enabled="true"
    fi
    
    echo "System AirDrop Status: $([ "$system_airdrop_enabled" == "true" ] && echo "ENABLED" || echo "DISABLED")"
    
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "=== Detailed Analysis ==="
        
        # Check user-level settings
        local users
        users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
        
        echo "User-Level AirDrop Settings:"
        for user in $users; do
            local user_setting
            user_setting=$(sudo -u "$user" defaults read com.apple.sharingd DiscoverableMode 2>/dev/null || echo "not_set")
            
            local setting_text
            case "$user_setting" in
                "0") setting_text="OFF" ;;
                "1") setting_text="CONTACTS ONLY" ;;
                "2") setting_text="EVERYONE" ;;
                *) setting_text="NOT SET" ;;
            esac
            
            echo "  $user: $setting_text"
        done
        
        # Check network connectivity
        echo ""
        echo "Network Interface Information:"
        echo "Wi-Fi Status: $(networksetup -getairportpower en0 | awk '{print $4}')"
        echo "Bluetooth Status: $(system_profiler SPBluetoothDataType | grep "State:" | awk '{print $2}' | head -1)"
        
        # Check running processes
        echo ""
        echo "Related Processes:"
        ps aux | grep -E "(sharingd|airportd)" | grep -v grep | awk '{print $11}'
    fi
}

# Comprehensive AirDrop policy enforcement
enforce_airdrop_policy() {
    local policy_name="$1"
    local target_users="$2"
    local dry_run="${3:-false}"
    
    log_action "Enforcing AirDrop policy: $policy_name (dry_run: $dry_run)"
    
    if [[ -z "${AIRDROP_POLICIES[$policy_name]}" ]]; then
        log_action "ERROR: Unknown policy '$policy_name'"
        echo "Available policies: ${!AIRDROP_POLICIES[*]}"
        return 1
    fi
    
    # Parse policy configuration
    IFS=',' read -ra POLICY_PARTS <<< "${AIRDROP_POLICIES[$policy_name]}"
    local airdrop_state="${POLICY_PARTS[0]}"
    local discovery_setting="${POLICY_PARTS[1]}"
    local monitoring_level="${POLICY_PARTS[2]}"
    local logging_level="${POLICY_PARTS[3]}"
    
    echo "=== Enforcing Policy: $policy_name ==="
    echo "AirDrop State: $airdrop_state"
    echo "Discovery Setting: $discovery_setting"
    echo "Monitoring Level: $monitoring_level"
    echo "Logging Level: $logging_level"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "DRY RUN MODE - No changes will be applied"
        return 0
    fi
    
    # Apply system-level settings
    case "$airdrop_state" in
        "enabled")
            echo "Enabling AirDrop system-wide..."
            sudo ifconfig awdl0 up
            ;;
        "disabled")
            echo "Disabling AirDrop system-wide..."
            sudo ifconfig awdl0 down
            ;;
    esac
    
    # Apply user-level settings
    if [[ "$target_users" == "all" ]]; then
        local users
        users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    else
        IFS=',' read -ra users <<< "$target_users"
    fi
    
    local discovery_value
    case "$discovery_setting" in
        "no_discovery") discovery_value="0" ;;
        "contacts_only") discovery_value="1" ;;
        "everyone") discovery_value="2" ;;
    esac
    
    for user in "${users[@]}"; do
        if id "$user" &>/dev/null; then
            echo "Applying settings for user: $user"
            sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int "$discovery_value"
            
            # Restart sharing daemon
            sudo -u "$user" killall sharingd 2>/dev/null
        fi
    done
    
    # Configure monitoring
    configure_airdrop_monitoring "$monitoring_level" "$logging_level"
    
    # Generate policy compliance report
    local report_file="$REPORT_DIR/policy_enforcement_${policy_name}_$(date +%Y%m%d_%H%M%S).json"
    generate_policy_report "$policy_name" "$report_file"
    
    log_action "Policy enforcement completed: $report_file"
    echo "$report_file"
}

# Configure AirDrop monitoring and logging
configure_airdrop_monitoring() {
    local monitoring_level="$1"
    local logging_level="$2"
    
    echo "Configuring monitoring (level: $monitoring_level, logging: $logging_level)"
    
    case "$monitoring_level" in
        "monitoring_enabled")
            # Create monitoring script
            cat > "/usr/local/bin/macfleet_airdrop_monitor.sh" << 'EOF'
#!/bin/bash
# AirDrop activity monitor
while true; do
    # Monitor AWDL interface changes
    ifconfig awdl0 | grep "status:" >> /var/log/macfleet_airdrop_activity.log
    sleep 30
done
EOF
            chmod +x "/usr/local/bin/macfleet_airdrop_monitor.sh"
            
            # Create LaunchDaemon for monitoring
            cat > "/Library/LaunchDaemons/com.macfleet.airdrop.monitor.plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.macfleet.airdrop.monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/macfleet_airdrop_monitor.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
EOF
            launchctl load "/Library/LaunchDaemons/com.macfleet.airdrop.monitor.plist"
            ;;
        "monitoring_disabled")
            # Remove monitoring components
            launchctl unload "/Library/LaunchDaemons/com.macfleet.airdrop.monitor.plist" 2>/dev/null
            rm -f "/Library/LaunchDaemons/com.macfleet.airdrop.monitor.plist"
            rm -f "/usr/local/bin/macfleet_airdrop_monitor.sh"
            ;;
    esac
}

# Generate comprehensive policy compliance report
generate_policy_report() {
    local policy_name="$1"
    local report_file="$2"
    
    # Get current system state
    local awdl_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}' || echo "unknown")
    local system_enabled="false"
    [[ "$awdl_status" == "active" ]] && system_enabled="true"
    
    # Get user settings
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    cat > "$report_file" << EOF
{
    "policy_report": {
        "policy_name": "$policy_name",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "script_version": "$SCRIPT_VERSION",
        "system_status": {
            "awdl_interface": "$awdl_status",
            "system_airdrop_enabled": $system_enabled
        },
        "user_settings": [],
        "compliance_status": "compliant",
        "recommendations": []
    }
}
EOF
    
    # Add user-specific settings
    for user in $users; do
        local user_setting
        user_setting=$(sudo -u "$user" defaults read com.apple.sharingd DiscoverableMode 2>/dev/null || echo "-1")
        
        jq --arg user "$user" \
           --argjson setting "$user_setting" \
           '.policy_report.user_settings += [{
               "username": $user,
               "discovery_mode": $setting,
               "discovery_text": (if $setting == 0 then "OFF" elif $setting == 1 then "CONTACTS_ONLY" elif $setting == 2 then "EVERYONE" else "NOT_SET" end)
           }]' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    done
    
    log_action "Policy report generated: $report_file"
}

# Fleet-wide AirDrop audit
audit_fleet_airdrop() {
    local scope="${1:-all}"
    
    echo "=== Fleet AirDrop Audit ==="
    log_action "Starting fleet AirDrop audit (scope: $scope)"
    
    local audit_report="$REPORT_DIR/fleet_airdrop_audit_$(date +%Y%m%d_%H%M%S).json"
    
    cat > "$audit_report" << EOF
{
    "audit_info": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "scope": "$scope",
        "audit_type": "airdrop_security"
    },
    "system_analysis": {},
    "user_analysis": [],
    "security_findings": [],
    "recommendations": []
}
EOF
    
    # System-level analysis
    local awdl_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}' || echo "unknown")
    local wifi_status=$(networksetup -getairportpower en0 | awk '{print $4}')
    local bluetooth_status=$(system_profiler SPBluetoothDataType | grep "State:" | awk '{print $2}' | head -1)
    
    jq --arg awdl "$awdl_status" \
       --arg wifi "$wifi_status" \
       --arg bluetooth "$bluetooth_status" \
       '.audit_info.system_analysis = {
           "awdl_interface": $awdl,
           "wifi_enabled": ($wifi == "On"),
           "bluetooth_enabled": ($bluetooth == "On"),
           "airdrop_capable": (($wifi == "On") and ($bluetooth == "On"))
       }' "$audit_report" > "${audit_report}.tmp" && mv "${audit_report}.tmp" "$audit_report"
    
    # User-level analysis
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    local security_issues=0
    
    for user in $users; do
        local discovery_mode
        discovery_mode=$(sudo -u "$user" defaults read com.apple.sharingd DiscoverableMode 2>/dev/null || echo "-1")
        
        local home_dir
        home_dir=$(dscl . -read "/Users/$user" NFSHomeDirectory 2>/dev/null | cut -d: -f2 | xargs)
        
        local is_admin="false"
        if dseditgroup -o checkmember -m "$user" admin &>/dev/null; then
            is_admin="true"
        fi
        
        # Check for security concerns
        local security_concern="none"
        if [[ "$discovery_mode" == "2" ]] && [[ "$is_admin" == "true" ]]; then
            security_concern="admin_user_unrestricted_airdrop"
            ((security_issues++))
        elif [[ "$discovery_mode" == "2" ]]; then
            security_concern="unrestricted_airdrop_enabled"
        fi
        
        jq --arg user "$user" \
           --argjson discovery "$discovery_mode" \
           --arg home "$home_dir" \
           --arg admin "$is_admin" \
           --arg concern "$security_concern" \
           '.audit_info.user_analysis += [{
               "username": $user,
               "discovery_mode": $discovery,
               "home_directory": $home,
               "is_admin": ($admin == "true"),
               "security_concern": $concern
           }]' "$audit_report" > "${audit_report}.tmp" && mv "${audit_report}.tmp" "$audit_report"
    done
    
    # Generate security summary
    jq --argjson issues "$security_issues" \
       '.audit_info.security_findings = [
           {
               "total_security_issues": $issues,
               "severity": (if $issues == 0 then "low" elif $issues < 3 then "medium" else "high" end),
               "compliance_status": (if $issues == 0 then "compliant" else "non_compliant" end)
           }
       ]' "$audit_report" > "${audit_report}.tmp" && mv "${audit_report}.tmp" "$audit_report"
    
    echo "Audit completed. Found $security_issues security issues."
    log_action "Fleet audit completed: $audit_report"
    echo "$audit_report"
}

# Main execution function
main() {
    local action="${1:-status}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    
    log_action "=== MacFleet AirDrop Management Started ==="
    log_action "Action: $action"
    
    # Ensure required privileges for most operations
    if [[ "$action" != "status" && "$action" != "help" && $EUID -ne 0 ]]; then
        echo "Error: This action requires administrator privileges"
        echo "Please run with sudo: sudo $0 $*"
        exit 1
    fi
    
    case "$action" in
        "disable")
            echo "Disabling AirDrop..."
            sudo ifconfig awdl0 down && echo "✓ AirDrop disabled" || echo "✗ Failed to disable AirDrop"
            ;;
        "enable")
            echo "Enabling AirDrop..."
            sudo ifconfig awdl0 up && echo "✓ AirDrop enabled" || echo "✗ Failed to enable AirDrop"
            ;;
        "status")
            monitor_airdrop_status "$param1"
            ;;
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Available policies: ${!AIRDROP_POLICIES[*]}"
                exit 1
            fi
            enforce_airdrop_policy "$param1" "${param2:-all}" "$param3"
            ;;
        "audit")
            audit_fleet_airdrop "$param1"
            ;;
        "user")
            if [[ -z "$param1" || -z "$param2" ]]; then
                echo "Usage: $0 user <username> <off|contacts|everyone>"
                exit 1
            fi
            manage_airdrop_discovery "$param1" "$param2"
            ;;
        "help")
            echo "Usage: $0 [action] [options...]"
            echo "Actions:"
            echo "  disable - Disable AirDrop system-wide"
            echo "  enable - Enable AirDrop system-wide"
            echo "  status [detailed] - Check AirDrop status"
            echo "  policy <policy_name> [users] [dry_run] - Apply policy"
            echo "  user <username> <setting> - Set user AirDrop setting"
            echo "  audit [scope] - Audit AirDrop security"
            echo "  help - Show this help"
            echo ""
            echo "Policies: ${!AIRDROP_POLICIES[*]}"
            ;;
        *)
            log_action "ERROR: Unknown action: $action"
            echo "Use '$0 help' for usage information"
            exit 1
            ;;
    esac
    
    log_action "=== AirDrop management completed ==="
}

# Execute main function
main "$@"

AirDrop Security Best Practices

Corporate Security Policies

#!/bin/bash

# Implement corporate AirDrop security policies
implement_corporate_security() {
    echo "=== Implementing Corporate AirDrop Security ==="
    
    # 1. Disable AirDrop on shared/public computers
    echo "Disabling AirDrop on shared workstations..."
    sudo ifconfig awdl0 down
    
    # 2. Set restrictive user defaults
    echo "Setting restrictive AirDrop defaults..."
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    for user in $users; do
        sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 0
    done
    
    # 3. Create system-wide policy enforcement
    cat > "/Library/Preferences/com.apple.sharingd.plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>DiscoverableMode</key>
    <integer>0</integer>
    <key>AirDropEnabled</key>
    <false/>
</dict>
</plist>
EOF
    
    # 4. Set proper permissions
    chmod 644 "/Library/Preferences/com.apple.sharingd.plist"
    chown root:wheel "/Library/Preferences/com.apple.sharingd.plist"
    
    echo "✓ Corporate security policies implemented"
}

implement_corporate_security

Compliance Monitoring

#!/bin/bash

# Monitor AirDrop compliance with security policies
monitor_compliance() {
    local compliance_standard="$1"
    
    echo "=== AirDrop Compliance Monitoring: $compliance_standard ==="
    
    case "$compliance_standard" in
        "hipaa")
            # Healthcare compliance - AirDrop must be disabled
            if ifconfig awdl0 | grep -q "status: active"; then
                echo "⚠ HIPAA VIOLATION: AirDrop is enabled"
                echo "Recommendation: Disable AirDrop to prevent PHI leakage"
                return 1
            else
                echo "✓ HIPAA COMPLIANT: AirDrop is disabled"
            fi
            ;;
        "pci_dss")
            # Payment card industry compliance
            if ifconfig awdl0 | grep -q "status: active"; then
                echo "⚠ PCI DSS VIOLATION: AirDrop creates uncontrolled network path"
                echo "Recommendation: Disable AirDrop in cardholder data environment"
                return 1
            else
                echo "✓ PCI DSS COMPLIANT: AirDrop is disabled"
            fi
            ;;
        "sox")
            # Sarbanes-Oxley compliance for financial data
            echo "Checking SOX compliance for financial data protection..."
            # Implementation specific to financial data handling
            ;;
        *)
            echo "Unknown compliance standard: $compliance_standard"
            return 1
            ;;
    esac
}

# Usage
monitor_compliance "hipaa"

Troubleshooting AirDrop Issues

Network Diagnostics

#!/bin/bash

# Comprehensive AirDrop troubleshooting
troubleshoot_airdrop() {
    echo "=== AirDrop Troubleshooting Diagnostics ==="
    
    echo "1. Checking AWDL Interface..."
    if ifconfig awdl0 &>/dev/null; then
        ifconfig awdl0 | head -10
    else
        echo "AWDL interface not available"
    fi
    
    echo -e "\n2. Checking Wi-Fi Status..."
    networksetup -getairportpower en0
    
    echo -e "\n3. Checking Bluetooth Status..."
    system_profiler SPBluetoothDataType | grep -A 5 "State:"
    
    echo -e "\n4. Checking Firewall Settings..."
    /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
    
    echo -e "\n5. Checking Sharing Preferences..."
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    for user in $users; do
        local setting
        setting=$(sudo -u "$user" defaults read com.apple.sharingd DiscoverableMode 2>/dev/null || echo "not set")
        echo "User $user: $setting"
    done
    
    echo -e "\n6. Checking Related Processes..."
    ps aux | grep -E "(sharingd|airportd|bluetoothd)" | grep -v grep
    
    echo -e "\n7. Network Interface Summary..."
    networksetup -listallhardwareports | grep -A 1 "Wi-Fi\|Bluetooth"
}

troubleshoot_airdrop

Reset AirDrop Configuration

#!/bin/bash

# Reset AirDrop to default configuration
reset_airdrop_config() {
    echo "=== Resetting AirDrop Configuration ==="
    
    # Stop sharing daemon
    echo "Stopping sharing daemon..."
    sudo killall sharingd 2>/dev/null
    
    # Reset AWDL interface
    echo "Resetting AWDL interface..."
    sudo ifconfig awdl0 down
    sleep 2
    sudo ifconfig awdl0 up
    
    # Clear user preferences
    echo "Clearing user AirDrop preferences..."
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    for user in $users; do
        echo "Resetting preferences for user: $user"
        sudo -u "$user" defaults delete com.apple.sharingd DiscoverableMode 2>/dev/null || true
    done
    
    # Remove system-wide policies
    echo "Removing system-wide AirDrop policies..."
    sudo rm -f "/Library/Preferences/com.apple.sharingd.plist"
    
    # Restart sharing daemon
    echo "Restarting sharing daemon..."
    sudo launchctl kickstart -k system/com.apple.sharingd
    
    echo "✓ AirDrop configuration reset to defaults"
}

reset_airdrop_config

Important Notes

  • AWDL Interface - Apple Wireless Direct Link is the underlying technology for AirDrop
  • Administrative privileges required for system-wide AirDrop control
  • User-level settings can override system policies unless enforced
  • Network dependencies - Requires both Wi-Fi and Bluetooth to be enabled
  • Security implications - Consider corporate policies before enabling
  • Compliance requirements - Some industries require AirDrop to be disabled
  • Test thoroughly - Validate changes on test devices before fleet deployment

Admin Rights Management on macOS

Manage and control administrator privileges across your MacFleet devices using advanced command-line tools and centralized privilege management policies. This tutorial covers temporary admin rights, privilege escalation control, security governance, and enterprise-grade admin rights management with comprehensive auditing and compliance capabilities.

Understanding macOS Admin Rights Management

macOS provides several tools and methods for managing administrator privileges:

  • dscl - Directory Services Command Line utility for user and group management
  • sudo - Execute commands with elevated privileges
  • launchctl - Launch daemon management for scheduled tasks
  • Groups framework - Built-in admin group membership management
  • Security Framework - Authorization and privilege validation

Enterprise admin rights management requires careful balance between security, productivity, and compliance requirements.

Basic Admin Rights Commands

Grant Admin Rights (Basic)

#!/bin/bash

# Basic admin rights grant
grant_admin_rights_basic() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage: grant_admin_rights_basic <username>"
        return 1
    fi
    
    # Verify user exists
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ User '$username' not found"
        return 1
    fi
    
    # Add user to admin group
    dscl . -append /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Admin rights granted to user: $username"
        return 0
    else
        echo "❌ Failed to grant admin rights to user: $username"
        return 1
    fi
}

# Example usage
# grant_admin_rights_basic "john.doe"

Revoke Admin Rights (Basic)

#!/bin/bash

# Basic admin rights revocation
revoke_admin_rights_basic() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage: revoke_admin_rights_basic <username>"
        return 1
    fi
    
    # Verify user exists
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ User '$username' not found"
        return 1
    fi
    
    # Remove user from admin group
    dscl . -delete /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Admin rights revoked from user: $username"
        return 0
    else
        echo "❌ Failed to revoke admin rights from user: $username"
        return 1
    fi
}

# Example usage
# revoke_admin_rights_basic "john.doe"

Check Admin Status

#!/bin/bash

# Check if user has admin privileges
check_admin_status() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage: check_admin_status <username>"
        return 1
    fi
    
    # Check if user is in admin group
    local admin_members
    admin_members=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | grep -o "$username")
    
    if [[ -n "$admin_members" ]]; then
        echo "✅ User '$username' has admin privileges"
        return 0
    else
        echo "❌ User '$username' does not have admin privileges"
        return 1
    fi
}

# List all admin users
list_admin_users() {
    echo "=== Current Admin Users ==="
    echo ""
    
    local admin_users
    admin_users=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | cut -d: -f2 | tr ' ' '\n' | grep -v '^$' | sort)
    
    if [[ -n "$admin_users" ]]; then
        echo "Administrator accounts:"
        while IFS= read -r user; do
            # Get user real name if available
            local real_name
            real_name=$(dscl . -read /Users/"$user" RealName 2>/dev/null | cut -d: -f2 | sed 's/^ *//')
            
            if [[ -n "$real_name" && "$real_name" != "$user" ]]; then
                echo "  • $user ($real_name)"
            else
                echo "  • $user"
            fi
        done <<< "$admin_users"
    else
        echo "No admin users found"
    fi
    echo ""
}

# Example usage
# check_admin_status "john.doe"
# list_admin_users

Advanced Admin Rights Management

Temporary Admin Rights

#!/bin/bash

# Enhanced temporary admin rights
grant_temporary_admin_rights() {
    local username="$1"
    local duration_minutes="${2:-30}"
    local reason="${3:-Administrative task}"
    local require_confirmation="${4:-true}"
    
    if [[ -z "$username" ]]; then
        echo "Usage: grant_temporary_admin_rights <username> [duration_minutes] [reason] [require_confirmation]"
        return 1
    fi
    
    # Verify user exists
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ User '$username' not found"
        return 1
    fi
    
    # Check if user already has admin rights
    if check_admin_status "$username" >/dev/null; then
        echo "⚠️  User '$username' already has admin privileges"
        read -p "Continue with temporary admin setup? (y/N): " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[Yy]$ ]]; then
            return 1
        fi
    fi
    
    # Display confirmation dialog if required
    if [[ "$require_confirmation" == "true" ]]; then
        osascript -e "display dialog \"You have been granted administrator rights for $duration_minutes minutes.\\n\\nReason: $reason\\n\\nPlease do not misuse this privilege.\" buttons {\"Accept Admin Rights\"} default button 1 with title \"MacFleet Admin Rights Grant\""
        
        if [[ $? -ne 0 ]]; then
            echo "❌ User declined admin rights grant"
            return 1
        fi
    fi
    
    # Create tracking directory
    local tracking_dir="/private/var/macfleet_admin_tracking"
    sudo mkdir -p "$tracking_dir"
    
    # Create user tracking file with metadata
    local tracking_file="$tracking_dir/${username}_admin.json"
    cat > "$tracking_file" <<EOF
{
    "username": "$username",
    "granted_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "duration_minutes": $duration_minutes,
    "reason": "$reason",
    "granted_by": "$(whoami)",
    "hostname": "$(hostname)",
    "pid": $$,
    "expires_at": "$(date -u -v+${duration_minutes}M +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
    
    # Grant admin rights
    dscl . -append /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Temporary admin rights granted to '$username' for $duration_minutes minutes"
        
        # Create removal script
        create_admin_removal_script "$username" "$duration_minutes"
        
        # Schedule removal
        schedule_admin_removal "$username" "$duration_minutes"
        
        return 0
    else
        echo "❌ Failed to grant admin rights to '$username'"
        rm -f "$tracking_file"
        return 1
    fi
}

# Create admin removal script
create_admin_removal_script() {
    local username="$1"
    local duration_minutes="$2"
    
    local script_path="/Library/Application Support/MacFleet/remove_admin_${username}.sh"
    mkdir -p "$(dirname "$script_path")"
    
    cat > "$script_path" <<'EOF'
#!/bin/bash

USERNAME="{{USERNAME}}"
TRACKING_DIR="/private/var/macfleet_admin_tracking"
TRACKING_FILE="$TRACKING_DIR/${USERNAME}_admin.json"
LOG_FILE="/var/log/macfleet_admin_rights.log"

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

log_action "Starting admin rights removal for user: $USERNAME"

# Check if user still has admin rights
if dscl . -read /Groups/admin GroupMembership 2>/dev/null | grep -q "$USERNAME"; then
    # Remove admin rights
    dscl . -delete /Groups/admin GroupMembership "$USERNAME"
    
    if [[ $? -eq 0 ]]; then
        log_action "✅ Admin rights successfully removed from user: $USERNAME"
        
        # Notify user if they're logged in
        if pgrep -u "$USERNAME" >/dev/null; then
            sudo -u "$USERNAME" osascript -e 'display notification "Your temporary administrator privileges have expired." with title "MacFleet Admin Rights"' 2>/dev/null
        fi
    else
        log_action "❌ Failed to remove admin rights from user: $USERNAME"
    fi
else
    log_action "⚠️  User $USERNAME did not have admin rights (already removed or never granted)"
fi

# Clean up tracking file
if [[ -f "$TRACKING_FILE" ]]; then
    # Archive the tracking data
    ARCHIVE_DIR="/var/log/macfleet_admin_archive"
    mkdir -p "$ARCHIVE_DIR"
    mv "$TRACKING_FILE" "$ARCHIVE_DIR/${USERNAME}_admin_$(date +%Y%m%d_%H%M%S).json"
    log_action "Admin rights tracking data archived for user: $USERNAME"
fi

# Remove launch daemon
PLIST_PATH="/Library/LaunchDaemons/com.macfleet.remove_admin_${USERNAME}.plist"
if [[ -f "$PLIST_PATH" ]]; then
    launchctl unload "$PLIST_PATH" 2>/dev/null
    rm -f "$PLIST_PATH"
    log_action "Launch daemon removed for user: $USERNAME"
fi

# Remove this script
rm -f "$0"

log_action "Admin rights removal process completed for user: $USERNAME"
exit 0
EOF
    
    # Replace placeholder with actual username
    sed -i '' "s/{{USERNAME}}/$username/g" "$script_path"
    
    # Set permissions
    chmod 755 "$script_path"
    chown root:wheel "$script_path"
}

# Schedule admin removal using launchd
schedule_admin_removal() {
    local username="$1"
    local duration_minutes="$2"
    
    local plist_path="/Library/LaunchDaemons/com.macfleet.remove_admin_${username}.plist"
    local script_path="/Library/Application Support/MacFleet/remove_admin_${username}.sh"
    
    # Calculate execution time
    local start_time
    start_time=$(date -u -v+${duration_minutes}M +%Y-%m-%dT%H:%M:%SZ)
    
    # Create launch daemon plist
    cat > "$plist_path" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.macfleet.remove_admin_${username}</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>${script_path}</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Year</key>
        <integer>$(date -u -v+${duration_minutes}M +%Y)</integer>
        <key>Month</key>
        <integer>$(date -u -v+${duration_minutes}M +%m)</integer>
        <key>Day</key>
        <integer>$(date -u -v+${duration_minutes}M +%d)</integer>
        <key>Hour</key>
        <integer>$(date -u -v+${duration_minutes}M +%H)</integer>
        <key>Minute</key>
        <integer>$(date -u -v+${duration_minutes}M +%M)</integer>
    </dict>
    <key>RunAtLoad</key>
    <false/>
</dict>
</plist>
EOF
    
    # Set permissions
    chown root:wheel "$plist_path"
    chmod 644 "$plist_path"
    
    # Load the daemon
    launchctl load "$plist_path"
    
    echo "⏰ Admin rights removal scheduled for $start_time"
}

# Example usage
# grant_temporary_admin_rights "john.doe" 30 "Software installation" true

Enterprise Admin Rights Management System

#!/bin/bash

# MacFleet Enterprise Admin Rights Management System
# Comprehensive privilege management, security governance, and compliance monitoring

# Configuration
LOG_FILE="/var/log/macfleet_admin_rights.log"
CONFIG_FILE="/etc/macfleet/admin_rights_config.conf"
AUDIT_DIR="/var/log/macfleet_admin_audit"
POLICY_DIR="/etc/macfleet/admin_policies"
TRACKING_DIR="/private/var/macfleet_admin_tracking"

# Create directory structure
setup_directories() {
    mkdir -p "$(dirname "$LOG_FILE")" "$AUDIT_DIR" "$POLICY_DIR" "$TRACKING_DIR" "$(dirname "$CONFIG_FILE")"
    touch "$LOG_FILE"
    
    # Set appropriate permissions
    chmod 755 "$AUDIT_DIR" "$POLICY_DIR"
    chmod 700 "$TRACKING_DIR"  # Restrict access to tracking data
}

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

# Load configuration
load_config() {
    if [[ -f "$CONFIG_FILE" ]]; then
        source "$CONFIG_FILE"
    else
        # Set defaults
        MAX_ADMIN_DURATION="${MAX_ADMIN_DURATION:-480}"  # 8 hours max
        DEFAULT_ADMIN_DURATION="${DEFAULT_ADMIN_DURATION:-30}"  # 30 minutes default
        REQUIRE_JUSTIFICATION="${REQUIRE_JUSTIFICATION:-true}"
        ENABLE_NOTIFICATIONS="${ENABLE_NOTIFICATIONS:-true}"
        AUDIT_ALL_CHANGES="${AUDIT_ALL_CHANGES:-true}"
        PROTECTED_ACCOUNTS="${PROTECTED_ACCOUNTS:-root,admin,macfleet}"
    fi
}

# Enterprise admin rights grant with policy enforcement
enterprise_grant_admin() {
    local username="$1"
    local duration_minutes="$2"
    local reason="$3"
    local approved_by="$4"
    
    load_config
    
    if [[ -z "$username" ]]; then
        log_action "ERROR: Username required for admin rights grant"
        return 1
    fi
    
    # Set default duration if not provided
    if [[ -z "$duration_minutes" ]]; then
        duration_minutes="$DEFAULT_ADMIN_DURATION"
    fi
    
    # Validate duration against policy
    if [[ "$duration_minutes" -gt "$MAX_ADMIN_DURATION" ]]; then
        log_action "ERROR: Requested duration ($duration_minutes min) exceeds maximum allowed ($MAX_ADMIN_DURATION min)"
        return 1
    fi
    
    # Require justification if policy enabled
    if [[ "$REQUIRE_JUSTIFICATION" == "true" && -z "$reason" ]]; then
        log_action "ERROR: Justification required for admin rights grant"
        return 1
    fi
    
    # Check if user exists
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        log_action "ERROR: User '$username' not found"
        return 1
    fi
    
    # Check for protected accounts
    if echo "$PROTECTED_ACCOUNTS" | grep -q "$username"; then
        log_action "ERROR: Cannot modify admin rights for protected account: $username"
        return 1
    fi
    
    # Check for existing admin rights
    local current_admin_status
    if check_admin_status "$username" >/dev/null; then
        current_admin_status="already_admin"
    else
        current_admin_status="standard_user"
    fi
    
    # Create audit entry
    local audit_id
    audit_id=$(create_audit_entry "grant" "$username" "$duration_minutes" "$reason" "$approved_by" "$current_admin_status")
    
    # Grant admin rights
    if [[ "$current_admin_status" == "standard_user" ]]; then
        dscl . -append /Groups/admin GroupMembership "$username"
        
        if [[ $? -ne 0 ]]; then
            log_action "ERROR: Failed to grant admin rights to '$username'"
            update_audit_entry "$audit_id" "failed" "Failed to modify admin group"
            return 1
        fi
    fi
    
    # Create tracking entry
    create_tracking_entry "$username" "$duration_minutes" "$reason" "$approved_by" "$audit_id"
    
    # Schedule removal if temporary
    if [[ "$duration_minutes" -gt 0 ]]; then
        schedule_enterprise_admin_removal "$username" "$duration_minutes" "$audit_id"
    fi
    
    # Send notifications
    if [[ "$ENABLE_NOTIFICATIONS" == "true" ]]; then
        send_admin_notification "$username" "granted" "$duration_minutes" "$reason"
    fi
    
    log_action "✅ Admin rights granted to '$username' for $duration_minutes minutes (Audit ID: $audit_id)"
    update_audit_entry "$audit_id" "success" "Admin rights granted successfully"
    
    return 0
}

# Enterprise admin rights revocation
enterprise_revoke_admin() {
    local username="$1"
    local reason="$2"
    local revoked_by="$3"
    
    load_config
    
    if [[ -z "$username" ]]; then
        log_action "ERROR: Username required for admin rights revocation"
        return 1
    fi
    
    # Check if user exists
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        log_action "ERROR: User '$username' not found"
        return 1
    fi
    
    # Check for protected accounts
    if echo "$PROTECTED_ACCOUNTS" | grep -q "$username"; then
        log_action "ERROR: Cannot modify admin rights for protected account: $username"
        return 1
    fi
    
    # Check current admin status
    if ! check_admin_status "$username" >/dev/null; then
        log_action "WARNING: User '$username' does not have admin privileges"
        return 0
    fi
    
    # Create audit entry
    local audit_id
    audit_id=$(create_audit_entry "revoke" "$username" "0" "$reason" "$revoked_by" "admin_user")
    
    # Remove admin rights
    dscl . -delete /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        log_action "✅ Admin rights revoked from '$username' (Audit ID: $audit_id)"
        
        # Clean up tracking
        cleanup_user_tracking "$username"
        
        # Cancel scheduled removal if exists
        cancel_scheduled_removal "$username"
        
        # Send notifications
        if [[ "$ENABLE_NOTIFICATIONS" == "true" ]]; then
            send_admin_notification "$username" "revoked" "0" "$reason"
        fi
        
        update_audit_entry "$audit_id" "success" "Admin rights revoked successfully"
        return 0
    else
        log_action "ERROR: Failed to revoke admin rights from '$username'"
        update_audit_entry "$audit_id" "failed" "Failed to modify admin group"
        return 1
    fi
}

# Create audit entry
create_audit_entry() {
    local action="$1"
    local username="$2"
    local duration="$3"
    local reason="$4"
    local operator="$5"
    local previous_status="$6"
    
    local audit_id="$(date +%s)_${username}_${action}"
    local audit_file="$AUDIT_DIR/${audit_id}.json"
    
    cat > "$audit_file" <<EOF
{
    "audit_id": "$audit_id",
    "action": "$action",
    "username": "$username",
    "duration_minutes": $duration,
    "reason": "$reason",
    "operator": "$operator",
    "previous_status": "$previous_status",
    "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "hostname": "$(hostname)",
    "system_info": {
        "macos_version": "$(sw_vers -productVersion)",
        "build_version": "$(sw_vers -buildVersion)"
    },
    "status": "pending",
    "completion_time": null,
    "result_message": null
}
EOF
    
    echo "$audit_id"
}

# Update audit entry
update_audit_entry() {
    local audit_id="$1"
    local status="$2"
    local message="$3"
    
    local audit_file="$AUDIT_DIR/${audit_id}.json"
    
    if [[ -f "$audit_file" ]]; then
        # Update status and completion time
        local temp_file=$(mktemp)
        jq --arg status "$status" --arg time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" --arg msg "$message" \
           '.status = $status | .completion_time = $time | .result_message = $msg' \
           "$audit_file" > "$temp_file" && mv "$temp_file" "$audit_file"
    fi
}

# Create tracking entry
create_tracking_entry() {
    local username="$1"
    local duration="$2"
    local reason="$3"
    local operator="$4"
    local audit_id="$5"
    
    local tracking_file="$TRACKING_DIR/${username}_admin.json"
    
    cat > "$tracking_file" <<EOF
{
    "username": "$username",
    "granted_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "duration_minutes": $duration,
    "expires_at": "$(date -u -v+${duration}M +%Y-%m-%dT%H:%M:%SZ)",
    "reason": "$reason",
    "granted_by": "$operator",
    "audit_id": "$audit_id",
    "hostname": "$(hostname)",
    "pid": $$,
    "status": "active"
}
EOF
}

# Schedule enterprise admin removal
schedule_enterprise_admin_removal() {
    local username="$1"
    local duration_minutes="$2"
    local audit_id="$3"
    
    local script_path="/Library/Application Support/MacFleet/enterprise_remove_admin_${username}.sh"
    local plist_path="/Library/LaunchDaemons/com.macfleet.enterprise_remove_admin_${username}.plist"
    
    # Create enhanced removal script
    mkdir -p "$(dirname "$script_path")"
    
    cat > "$script_path" <<EOF
#!/bin/bash

# MacFleet Enterprise Admin Rights Removal
USERNAME="$username"
AUDIT_ID="$audit_id"
LOG_FILE="$LOG_FILE"
TRACKING_DIR="$TRACKING_DIR"
AUDIT_DIR="$AUDIT_DIR"

# Source the main script functions
source /usr/local/bin/macfleet_admin_management.sh

log_action "Starting scheduled admin rights removal for user: \$USERNAME (Audit ID: \$AUDIT_ID)"

# Remove admin rights
enterprise_revoke_admin "\$USERNAME" "Automatic expiration" "system"

# Clean up launch daemon
launchctl unload "$plist_path" 2>/dev/null
rm -f "$plist_path"
rm -f "\$0"

log_action "Scheduled admin rights removal completed for user: \$USERNAME"
exit 0
EOF
    
    chmod 755 "$script_path"
    chown root:wheel "$script_path"
    
    # Create launch daemon
    create_removal_launch_daemon "$username" "$duration_minutes" "$script_path" "$plist_path"
}

# Send admin notifications
send_admin_notification() {
    local username="$1"
    local action="$2"
    local duration="$3"
    local reason="$4"
    
    local message
    case "$action" in
        "granted")
            if [[ "$duration" -gt 0 ]]; then
                message="Administrator privileges granted for $duration minutes. Reason: $reason"
            else
                message="Administrator privileges granted permanently. Reason: $reason"
            fi
            ;;
        "revoked")
            message="Administrator privileges have been revoked. Reason: $reason"
            ;;
        "expired")
            message="Temporary administrator privileges have expired."
            ;;
    esac
    
    # Send notification to user if logged in
    if pgrep -u "$username" >/dev/null; then
        sudo -u "$username" osascript -e "display notification \"$message\" with title \"MacFleet Admin Rights\"" 2>/dev/null
    fi
    
    # Log notification
    log_action "Notification sent to '$username': $message"
}

# Admin rights security audit
perform_admin_audit() {
    local audit_file="$AUDIT_DIR/security_audit_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Performing admin rights security audit: $audit_file"
    
    {
        echo "{"
        echo "  \"audit_type\": \"admin_rights_security\","
        echo "  \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
        echo "  \"hostname\": \"$(hostname)\","
        echo "  \"auditor\": \"$(whoami)\","
        
        # Current admin users analysis
        echo "  \"current_admin_users\": ["
        local admin_users
        admin_users=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | cut -d: -f2 | tr ' ' '\n' | grep -v '^$' | sort)
        
        local first_user=true
        while IFS= read -r user; do
            if [[ -n "$user" ]]; then
                if [[ "$first_user" == "false" ]]; then
                    echo ","
                fi
                first_user=false
                
                local real_name uid last_login
                real_name=$(dscl . -read /Users/"$user" RealName 2>/dev/null | cut -d: -f2 | sed 's/^ *//')
                uid=$(dscl . -read /Users/"$user" UniqueID 2>/dev/null | awk '{print $2}')
                last_login=$(last -1 "$user" 2>/dev/null | head -1 | awk '{print $4, $5, $6, $7}')
                
                echo "    {"
                echo "      \"username\": \"$user\","
                echo "      \"real_name\": \"${real_name:-Unknown}\","
                echo "      \"uid\": \"${uid:-Unknown}\","
                echo "      \"last_login\": \"${last_login:-Never}\","
                
                # Check if user has active tracking
                local tracking_file="$TRACKING_DIR/${user}_admin.json"
                if [[ -f "$tracking_file" ]]; then
                    local expires_at reason
                    expires_at=$(jq -r '.expires_at' "$tracking_file" 2>/dev/null)
                    reason=$(jq -r '.reason' "$tracking_file" 2>/dev/null)
                    
                    echo "      \"temporary_admin\": true,"
                    echo "      \"expires_at\": \"$expires_at\","
                    echo "      \"reason\": \"$reason\""
                else
                    echo "      \"temporary_admin\": false,"
                    echo "      \"expires_at\": null,"
                    echo "      \"reason\": null"
                fi
                echo -n "    }"
            fi
        done <<< "$admin_users"
        echo ""
        echo "  ],"
        
        # Active tracking entries
        echo "  \"active_temporary_admin\": ["
        local first_tracking=true
        for tracking_file in "$TRACKING_DIR"/*_admin.json; do
            if [[ -f "$tracking_file" ]]; then
                if [[ "$first_tracking" == "false" ]]; then
                    echo ","
                fi
                first_tracking=false
                cat "$tracking_file"
            fi
        done
        echo ""
        echo "  ],"
        
        # Recent audit entries (last 24 hours)
        echo "  \"recent_admin_changes\": ["
        local cutoff_time
        cutoff_time=$(date -u -v-1d +%s)
        local first_audit=true
        
        for audit_file in "$AUDIT_DIR"/*.json; do
            if [[ -f "$audit_file" ]]; then
                local audit_timestamp
                audit_timestamp=$(jq -r '.timestamp' "$audit_file" 2>/dev/null)
                local audit_epoch
                audit_epoch=$(date -jf "%Y-%m-%dT%H:%M:%SZ" "$audit_timestamp" +%s 2>/dev/null)
                
                if [[ "$audit_epoch" -gt "$cutoff_time" ]]; then
                    if [[ "$first_audit" == "false" ]]; then
                        echo ","
                    fi
                    first_audit=false
                    cat "$audit_file"
                fi
            fi
        done
        echo ""
        echo "  ]"
        echo "}"
    } > "$audit_file"
    
    log_action "Admin rights security audit completed: $audit_file"
    echo "$audit_file"
}

# Main management function
main() {
    local action="${1:-status}"
    local parameter1="$2"
    local parameter2="$3"
    local parameter3="$4"
    local parameter4="$5"
    
    setup_directories
    log_action "MacFleet Admin Rights Management started with action: $action"
    
    case "$action" in
        "grant")
            enterprise_grant_admin "$parameter1" "$parameter2" "$parameter3" "$parameter4"
            ;;
        "revoke")
            enterprise_revoke_admin "$parameter1" "$parameter2" "$parameter3"
            ;;
        "temp"|"temporary")
            grant_temporary_admin_rights "$parameter1" "$parameter2" "$parameter3" "$parameter4"
            ;;
        "check")
            check_admin_status "$parameter1"
            ;;
        "list")
            list_admin_users
            ;;
        "audit")
            perform_admin_audit
            ;;
        "status"|*)
            list_admin_users
            ;;
    esac
    
    log_action "MacFleet Admin Rights Management completed with action: $action"
}

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

Admin Rights Policy Templates

Corporate Admin Rights Policy

# /etc/macfleet/admin_rights_config.conf
# MacFleet Corporate Admin Rights Configuration

# Duration limits (in minutes)
MAX_ADMIN_DURATION="480"        # 8 hours maximum
DEFAULT_ADMIN_DURATION="30"     # 30 minutes default
WARNING_BEFORE_EXPIRY="5"       # 5 minutes warning

# Security requirements
REQUIRE_JUSTIFICATION="true"
REQUIRE_APPROVAL="true"
MINIMUM_JUSTIFICATION_LENGTH="10"

# Notification settings
ENABLE_NOTIFICATIONS="true"
NOTIFY_SECURITY_TEAM="true"
SECURITY_TEAM_EMAIL="security@company.com"

# Audit settings
AUDIT_ALL_CHANGES="true"
RETAIN_AUDIT_LOGS="90"          # 90 days
ENABLE_REALTIME_MONITORING="true"

# Protected accounts (cannot be modified)
PROTECTED_ACCOUNTS="root,admin,macfleet,security"

# Approval workflow
REQUIRE_MANAGER_APPROVAL="true"
ENABLE_EMERGENCY_BYPASS="false"
EMERGENCY_BYPASS_ACCOUNTS="security,ciso"

High Security Environment Policy

# /etc/macfleet/admin_policies/high_security.policy
# MacFleet High Security Admin Rights Policy

# Strict duration limits
MAX_ADMIN_DURATION="60"         # 1 hour maximum
DEFAULT_ADMIN_DURATION="15"     # 15 minutes default
AUTO_REVOKE_IDLE="true"         # Revoke if user idle
IDLE_TIMEOUT_MINUTES="10"       # 10 minutes idle timeout

# Enhanced security
REQUIRE_JUSTIFICATION="true"
REQUIRE_TWO_PERSON_APPROVAL="true"
ENABLE_SESSION_RECORDING="true"
BLOCK_ADMIN_OUTSIDE_HOURS="true"
ALLOWED_HOURS="09-17"           # 9 AM to 5 PM
ALLOWED_DAYS="1-5"              # Monday to Friday

# Monitoring
ENABLE_REALTIME_ALERTS="true"
ALERT_ON_ADMIN_GRANT="true"
ALERT_ON_SUSPICIOUS_ACTIVITY="true"
LOG_ALL_ADMIN_COMMANDS="true"

Security and Compliance Functions

Admin Rights Compliance Check

#!/bin/bash

# Comprehensive admin rights compliance check
check_admin_compliance() {
    echo "🔍 Admin Rights Compliance Check"
    echo "==============================="
    echo ""
    
    local compliance_issues=()
    local compliance_warnings=()
    
    # Check for unauthorized permanent admin accounts
    echo "1. UNAUTHORIZED PERMANENT ADMIN ACCOUNTS:"
    echo "----------------------------------------"
    
    local admin_users
    admin_users=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | cut -d: -f2 | tr ' ' '\n' | grep -v '^$')
    
    while IFS= read -r user; do
        if [[ -n "$user" ]]; then
            local tracking_file="$TRACKING_DIR/${user}_admin.json"
            
            # Skip protected accounts
            if echo "$PROTECTED_ACCOUNTS" | grep -q "$user"; then
                echo "  ✅ $user (Protected account)"
                continue
            fi
            
            # Check if user has temporary admin tracking
            if [[ ! -f "$tracking_file" ]]; then
                # No tracking = permanent admin (potential violation)
                compliance_issues+=("Permanent admin account without tracking: $user")
                echo "  ❌ $user (No temporary admin tracking found)"
            else
                # Check if temporary admin has expired
                local expires_at
                expires_at=$(jq -r '.expires_at' "$tracking_file" 2>/dev/null)
                local current_time
                current_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)
                
                if [[ "$expires_at" < "$current_time" ]]; then
                    compliance_issues+=("Expired temporary admin still active: $user")
                    echo "  ⚠️  $user (Temporary admin expired but still active)"
                else
                    local reason
                    reason=$(jq -r '.reason' "$tracking_file" 2>/dev/null)
                    echo "  ✅ $user (Temporary admin, expires: $expires_at, reason: $reason)"
                fi
            fi
        fi
    done <<< "$admin_users"
    echo ""
    
    # Check for stale tracking files
    echo "2. STALE TRACKING FILES:"
    echo "-----------------------"
    
    for tracking_file in "$TRACKING_DIR"/*_admin.json; do
        if [[ -f "$tracking_file" ]]; then
            local username
            username=$(basename "$tracking_file" _admin.json)
            
            # Check if user still has admin rights
            if ! check_admin_status "$username" >/dev/null 2>&1; then
                compliance_warnings+=("Stale tracking file for non-admin user: $username")
                echo "  ⚠️  Stale tracking file: $tracking_file"
            fi
        fi
    done
    echo ""
    
    # Check audit log integrity
    echo "3. AUDIT LOG INTEGRITY:"
    echo "----------------------"
    
    local recent_changes
    recent_changes=$(find "$AUDIT_DIR" -name "*.json" -mtime -1 | wc -l | tr -d ' ')
    
    if [[ "$recent_changes" -eq 0 ]]; then
        compliance_warnings+=("No admin rights changes in last 24 hours")
        echo "  ℹ️  No admin rights changes recorded in last 24 hours"
    else
        echo "  ✅ $recent_changes admin rights changes recorded in last 24 hours"
    fi
    echo ""
    
    # Generate compliance summary
    echo "4. COMPLIANCE SUMMARY:"
    echo "---------------------"
    
    if [[ ${#compliance_issues[@]} -eq 0 ]]; then
        echo "  ✅ No critical compliance issues found"
    else
        echo "  ❌ Critical compliance issues found:"
        for issue in "${compliance_issues[@]}"; do
            echo "    - $issue"
        done
    fi
    
    if [[ ${#compliance_warnings[@]} -gt 0 ]]; then
        echo "  ⚠️  Warnings:"
        for warning in "${compliance_warnings[@]}"; do
            echo "    - $warning"
        done
    fi
    
    echo ""
    echo "Recommendations:"
    echo "• Review and remediate any unauthorized permanent admin accounts"
    echo "• Implement regular compliance checks (daily/weekly)"
    echo "• Enable real-time monitoring for admin rights changes"
    echo "• Establish clear admin rights governance policies"
    echo "• Regular audit of admin activities and justifications"
    
    # Return appropriate exit code
    if [[ ${#compliance_issues[@]} -gt 0 ]]; then
        return 1
    else
        return 0
    fi
}

check_admin_compliance

Important Technical Notes

DSCL Command Reference

  • dscl . -append /Groups/admin GroupMembership <user>: Add user to admin group
  • dscl . -delete /Groups/admin GroupMembership <user>: Remove user from admin group
  • dscl . -read /Groups/admin GroupMembership: List all admin group members
  • dscl . -read /Users/<user>: Get detailed user information

Security Considerations

  1. Principle of Least Privilege: Grant minimum necessary privileges for minimum time
  2. Audit Trail: Maintain comprehensive logs of all admin rights changes
  3. Approval Workflow: Implement approval processes for admin rights grants
  4. Time Limits: Always use temporary admin rights with automatic expiration
  5. Monitoring: Real-time monitoring of admin activities and suspicious behavior

Compliance Requirements

  1. Documentation: Maintain detailed records of admin rights grants and revocations
  2. Justification: Require business justification for all privilege escalations
  3. Regular Audits: Perform regular compliance checks and reviews
  4. Protected Accounts: Safeguard critical system accounts from modification
  5. Retention Policies: Implement appropriate log retention and archival

Enterprise Use Cases

  1. Software Installation: Temporary admin rights for application installations
  2. System Maintenance: Scheduled admin access for maintenance windows
  3. Emergency Response: Rapid privilege escalation for incident response
  4. Compliance Auditing: Regular reviews of admin rights and activities
  5. Zero Trust Security: Continuous verification and minimal privilege access

Remember to test all scripts on individual devices before deploying across your MacFleet environment, and ensure compliance with corporate security policies and regulatory requirements when implementing enterprise admin rights management systems.

Configuring a GitHub Actions Runner on a Mac Mini (Apple Silicon)

GitHub Actions runner

GitHub Actions is a powerful CI/CD platform that allows you to automate your software development workflows. While GitHub offers hosted runners, self-hosted runners provide increased control and customization for your CI/CD setup. This tutorial guides you through setting up, configuring, and connecting a self-hosted runner on a Mac mini to execute macOS pipelines.

Prerequisites

Before you begin, ensure you have:

  • A Mac mini (register on Macfleet)
  • A GitHub repository with administrator rights
  • A package manager installed (preferably Homebrew)
  • Git installed on your system

Step 1: Create a Dedicated User Account

First, create a dedicated user account for the GitHub Actions runner:

# Create the 'gh-runner' user account
sudo dscl . -create /Users/gh-runner
sudo dscl . -create /Users/gh-runner UserShell /bin/bash
sudo dscl . -create /Users/gh-runner RealName "GitHub runner"
sudo dscl . -create /Users/gh-runner UniqueID "1001"
sudo dscl . -create /Users/gh-runner PrimaryGroupID 20
sudo dscl . -create /Users/gh-runner NFSHomeDirectory /Users/gh-runner

# Set the password for the user
sudo dscl . -passwd /Users/gh-runner your_password

# Add 'gh-runner' to the 'admin' group
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Switch to the new user account:

su gh-runner

Step 2: Install Required Software

Install Git and Rosetta 2 (if using Apple Silicon):

# Install Git if not already installed
brew install git

# Install Rosetta 2 for Apple Silicon Macs
softwareupdate --install-rosetta

Step 3: Configure the GitHub Actions Runner

  1. Go to your GitHub repository
  2. Navigate to Settings > Actions > Runners

GitHub Actions runner

  1. Click "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Select macOS as the runner image and ARM64 as the architecture
  3. Follow the provided commands to download and configure the runner

GitHub Actions runner

Create a .env file in the runner's _work directory:

# _work/.env file
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Execute the run.sh script in your runner directory to complete the setup.
  2. Verify that the runner is up and listening for jobs in the terminal and check the GitHub repository settings for the runner's association and Idle status.

GitHub Actions runner

Step 4: Configure Sudoers (Optional)

If your actions require root privileges, configure the sudoers file:

sudo visudo

Add the following line:

gh-runner ALL=(ALL) NOPASSWD: ALL

Step 5: Using the Runner in Workflows

Configure your GitHub Actions workflow to use the self-hosted runner:

name: Sample workflow

on:
  workflow_dispatch:

jobs:
  build:
    runs-on: [self-hosted, macOS, ARM64]
    steps:
      - name: Install NodeJS
        run: brew install node

The runner is authenticated to your repository and labeled with self-hosted, macOS, and ARM64. Use it in your workflows by specifying these labels in the runs-on field:

runs-on: [self-hosted, macOS, ARM64]

Best Practices

  • Keep your runner software up to date
  • Regularly monitor runner logs for issues
  • Use specific labels for different types of runners
  • Implement proper security measures
  • Consider using multiple runners for load balancing

Troubleshooting

Common issues and solutions:

  1. Runner not connecting:

    • Check network connectivity
    • Verify GitHub token validity
    • Ensure proper permissions
  2. Build failures:

    • Check Xcode installation
    • Verify required dependencies
    • Review workflow logs
  3. Permission issues:

    • Verify user permissions
    • Check sudoers configuration
    • Review file system permissions

Conclusion

You now have a self-hosted GitHub Actions runner configured on your Mac mini. This setup provides you with more control over your CI/CD environment and allows you to run macOS-specific workflows efficiently.

Remember to regularly maintain your runner and keep it updated with the latest security patches and software versions.

Native App

Macfleet native app

Macfleet Installation Guide

Macfleet is a powerful fleet management solution designed specifically for cloud-hosted Mac Mini environments. As a Mac Mini cloud hosting provider, you can use Macfleet to monitor, manage, and optimize your entire fleet of virtualized Mac instances.

This installation guide will walk you through setting up Macfleet monitoring across macOS, Windows, and Linux systems to ensure comprehensive oversight of your cloud infrastructure.

🍎 macOS

  • Download the .dmg file for Mac here
  • Double-click the downloaded .dmg file
  • Drag the Macfleet app to the Applications folder
  • Eject the .dmg file
  • Open System Preferences > Security & Privacy
    • Privacy tab > Accessibility
    • Check Macfleet to allow monitoring
  • Launch Macfleet from Applications
  • Tracking starts automatically

🪟 Windows

  • Download the .exe file for Windows here
  • Right-click the .exe file > "Run as administrator"
  • Follow the installation wizard
  • Accept terms and conditions
  • Allow in Windows Defender if prompted
  • Grant application monitoring permissions
  • Launch Macfleet from Start Menu
  • The application begins tracking automatically

🐧 Linux

  • Download the .deb package (Ubuntu/Debian) or .rpm (CentOS/RHEL) here
  • Install using your package manager
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Allow X11 access permissions if prompted
  • Add user to appropriate groups if necessary
  • Launch Macfleet from Applications menu
  • The application begins tracking automatically

Note: After installation on all systems, log in with your Macfleet credentials to sync data with your dashboard.