Guide

Nouvelles mises à jour et améliorations de Roundfleet.

Gestion d'Inventaire App Store sur macOS

Gérez et suivez efficacement les applications App Store sur vos appareils Roundfleet avec des outils d'inventaire complets. Ce tutoriel couvre la découverte d'applications, la conformité des licences, l'analyse d'utilisation et les rapports de niveau entreprise pour les applications Mac App Store.

Comprendre la Gestion des Applications App Store

Les applications App Store sur macOS contiennent des identifiants uniques et des reçus qui permettent le suivi d'entreprise :

Composants Principaux

  • Reçus MAS - Reçus numériques stockés dans les bundles d'applications pour vérification
  • Identifiants Bundle - Identification unique d'application dans l'écosystème App Store
  • Suivi Version - Gestion version d'application et conformité mise à jour
  • Gestion Licence - Surveillance allocation et conformité licence d'entreprise
  • Analyse Utilisation - Modèles d'utilisation d'application et métriques d'adoption

Avantages Entreprise

  • Gestion Actifs Logiciels - Inventaire complet des applications App Store
  • Conformité Licence - Suivi licences et allocations d'applications d'entreprise
  • Surveillance Sécurité - Identifier applications non autorisées ou non conformes
  • Optimisation Coûts - Optimiser dépenses App Store et utilisation licences
  • Application Politique - Assurer conformité avec politiques d'applications d'entreprise

Découverte Basique des Applications App Store

Liste Simple Applications App Store

#!/bin/bash

# Découverte basique applications App Store
echo "📱 Découverte Applications App Store"
echo "===================================="
echo ""

app_store_apps=$(find /Applications -path '*Contents/_MASReceipt/receipt' -maxdepth 4 -print | \
    sed 's#.app/Contents/_MASReceipt/receipt#.app#g; s#/Applications/##')

if [[ -n "$app_store_apps" ]]; then
    echo "Applications App Store Trouvées :"
    echo "$app_store_apps" | sort
    
    local app_count=$(echo "$app_store_apps" | wc -l | xargs)
    echo ""
    echo "Total applications App Store : $app_count"
else
    echo "Aucune application App Store trouvée dans /Applications"
fi

Découverte Améliorée avec Détails

#!/bin/bash

# Découverte complète applications App Store avec métadonnées
discover_app_store_apps() {
    echo "🔍 Découverte Complète Applications App Store"
    echo "============================================="
    echo ""
    
    local apps_found=0
    local total_size=0
    
    # Trouver toutes applications App Store avec reçus
    while IFS= read -r -d '' app_path; do
        if [[ -n "$app_path" ]]; then
            local app_name=$(basename "$app_path" .app)
            local app_bundle_id=""
            local app_version=""
            local app_size=""
            local install_date=""
            
            # Obtenir identifiant bundle
            if [[ -f "$app_path/Contents/Info.plist" ]]; then
                app_bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Inconnu")
                app_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Inconnue")
            fi
            
            # Obtenir taille application
            if [[ -d "$app_path" ]]; then
                app_size=$(du -sh "$app_path" 2>/dev/null | cut -f1 || echo "Inconnue")
                # Convertir taille en octets pour totalisation
                local size_bytes=$(du -s "$app_path" 2>/dev/null | cut -f1 || echo "0")
                total_size=$((total_size + size_bytes))
            fi
            
            # Obtenir date installation/modification
            if [[ -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
                install_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "Inconnue")
            fi
            
            echo "App : $app_name"
            echo "  ID Bundle : $app_bundle_id"
            echo "  Version : $app_version"
            echo "  Taille : $app_size"
            echo "  Date Installation : $install_date"
            echo "  Chemin : $app_path"
            echo ""
            
            ((apps_found++))
        fi
    done < <(find /Applications -name "*.app" -path '*Contents/_MASReceipt/receipt' -exec dirname {} \; 2>/dev/null | \
             sed 's|/Contents/_MASReceipt||' | sort -u | tr '\n' '\0')
    
    # Statistiques résumé
    echo "=== Résumé Découverte ==="
    echo "Total applications App Store trouvées : $apps_found"
    echo "Espace disque total utilisé : $(echo "scale=2; $total_size / 1024 / 1024" | bc 2>/dev/null || echo "Inconnu") MB"
    echo "Taille moyenne application : $(echo "scale=2; $total_size / $apps_found / 1024 / 1024" | bc 2>/dev/null || echo "Inconnue") MB"
    echo "Scan terminé : $(date)"
    
    return $apps_found
}

# Exécuter découverte
discover_app_store_apps

Gestion d'Inventaire d'Applications d'Entreprise

Script d'Inventaire Complet

#!/bin/bash

# Gestion inventaire App Store d'entreprise
generate_app_store_inventory() {
    local output_format="${1:-json}"
    local include_metadata="${2:-true}"
    local export_path="${3:-/tmp}"
    
    echo "📊 Génération Inventaire App Store d'Entreprise"
    echo "==============================================="
    echo "Format sortie : $output_format"
    echo "Inclure métadonnées : $include_metadata"
    echo ""
    
    local timestamp=$(date +"%Y%m%d_%H%M%S")
    local hostname=$(hostname)
    local report_file="$export_path/app_store_inventory_${hostname}_${timestamp}"
    
    # Informations système
    local device_info=$(system_profiler SPHardwareDataType | grep -E "(Model Name|Serial Number)" | \
                        awk -F': ' '{print $2}' | xargs | tr ' ' '_')
    local macos_version=$(sw_vers -productVersion)
    local current_user=$(stat -f%Su /dev/console 2>/dev/null || echo "$USER")
    
    # Initialiser structure données inventaire
    local inventory_data=""
    local app_count=0
    local total_size_bytes=0
    
    echo "Scan applications..."
    
    # Découvrir toutes applications App Store
    while IFS= read -r -d '' app_path; do
        if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
            local app_name=$(basename "$app_path" .app)
            local bundle_id=""
            local version=""
            local build_version=""
            local size_bytes=0
            local size_human=""
            local install_date=""
            local last_modified=""
            local executable_path=""
            local app_category=""
            local developer_name=""
            local app_store_url=""
            
            # Extraire métadonnées application
            if [[ -f "$app_path/Contents/Info.plist" ]]; then
                bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "inconnu")
                version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "inconnue")
                build_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleVersion 2>/dev/null || echo "inconnue")
                executable_path=$(defaults read "$app_path/Contents/Info.plist" CFBundleExecutable 2>/dev/null || echo "inconnu")
                app_category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "inconnue")
            fi
            
            # Obtenir taille application
            size_bytes=$(du -sk "$app_path" 2>/dev/null | cut -f1 || echo "0")
            size_bytes=$((size_bytes * 1024))  # Convertir KB en octets
            size_human=$(du -sh "$app_path" 2>/dev/null | cut -f1 || echo "inconnue")
            total_size_bytes=$((total_size_bytes + size_bytes))
            
            # Obtenir horodatages
            install_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "inconnue")
            last_modified=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path" 2>/dev/null || echo "inconnue")
            
            # Essayer d'extraire métadonnées supplémentaires si demandé
            if [[ "$include_metadata" == "true" ]]; then
                # Chercher identifiant équipe
                local team_id=""
                if command -v codesign >/dev/null 2>&1; then
                    team_id=$(codesign -dv "$app_path" 2>&1 | grep "TeamIdentifier" | awk -F'=' '{print $2}' || echo "inconnu")
                fi
                
                # Vérifier si application en cours d'exécution
                local is_running="false"
                if pgrep -f "$app_name" >/dev/null 2>&1; then
                    is_running="true"
                fi
                
                # Obtenir permissions application (vérification simplifiée)
                local has_camera_permission="inconnue"
                local has_microphone_permission="inconnue"
                local has_location_permission="inconnue"
                
                if [[ -f "$app_path/Contents/Info.plist" ]]; then
                    if defaults read "$app_path/Contents/Info.plist" NSCameraUsageDescription >/dev/null 2>&1; then
                        has_camera_permission="demandee"
                    else
                        has_camera_permission="non_demandee"
                    fi
                    
                    if defaults read "$app_path/Contents/Info.plist" NSMicrophoneUsageDescription >/dev/null 2>&1; then
                        has_microphone_permission="demandee"
                    else
                        has_microphone_permission="non_demandee"
                    fi
                    
                    if defaults read "$app_path/Contents/Info.plist" NSLocationUsageDescription >/dev/null 2>&1; then
                        has_location_permission="demandee"
                    else
                        has_location_permission="non_demandee"
                    fi
                fi
            fi
            
            # Formater sortie basée sur format demandé
            case "$output_format" in
                "json")
                    local app_json="{
                        \"nom_app\": \"$app_name\",
                        \"bundle_id\": \"$bundle_id\",
                        \"version\": \"$version\",
                        \"version_build\": \"$build_version\",
                        \"taille_octets\": $size_bytes,
                        \"taille_humaine\": \"$size_human\",
                        \"date_installation\": \"$install_date\",
                        \"derniere_modification\": \"$last_modified\",
                        \"chemin_app\": \"$app_path\",
                        \"chemin_executable\": \"$executable_path\",
                        \"categorie\": \"$app_category\""
                    
                    if [[ "$include_metadata" == "true" ]]; then
                        app_json="$app_json,
                        \"id_equipe\": \"$team_id\",
                        \"en_cours_execution\": $is_running,
                        \"permission_camera\": \"$has_camera_permission\",
                        \"permission_microphone\": \"$has_microphone_permission\",
                        \"permission_localisation\": \"$has_location_permission\""
                    fi
                    
                    app_json="$app_json}"
                    
                    if [[ $app_count -gt 0 ]]; then
                        inventory_data="$inventory_data,$app_json"
                    else
                        inventory_data="$app_json"
                    fi
                    ;;
                    
                "csv")
                    if [[ $app_count -eq 0 ]]; then
                        # En-tête CSV
                        if [[ "$include_metadata" == "true" ]]; then
                            inventory_data="Nom App,Bundle ID,Version,Version Build,Taille (Octets),Taille (Humaine),Date Installation,Dernière Modification,Chemin App,Catégorie,ID Équipe,En Cours Exécution,Permission Caméra,Permission Microphone,Permission Localisation"
                        else
                            inventory_data="Nom App,Bundle ID,Version,Version Build,Taille (Octets),Taille (Humaine),Date Installation,Dernière Modification,Chemin App,Catégorie"
                        fi
                    fi
                    
                    local csv_line="\"$app_name\",\"$bundle_id\",\"$version\",\"$build_version\",$size_bytes,\"$size_human\",\"$install_date\",\"$last_modified\",\"$app_path\",\"$app_category\""
                    
                    if [[ "$include_metadata" == "true" ]]; then
                        csv_line="$csv_line,\"$team_id\",$is_running,\"$has_camera_permission\",\"$has_microphone_permission\",\"$has_location_permission\""
                    fi
                    
                    inventory_data="$inventory_data\n$csv_line"
                    ;;
                    
                "text"|*)
                    inventory_data="$inventory_data
App : $app_name
  Bundle ID : $bundle_id
  Version : $version ($build_version)
  Taille : $size_human ($size_bytes octets)
  Date Installation : $install_date
  Dernière Modification : $last_modified
  Chemin : $app_path
  Catégorie : $app_category"
                    
                    if [[ "$include_metadata" == "true" ]]; then
                        inventory_data="$inventory_data
  ID Équipe : $team_id
  Actuellement En Cours : $is_running
  Permission Caméra : $has_camera_permission
  Permission Microphone : $has_microphone_permission
  Permission Localisation : $has_location_permission"
                    fi
                    
                    inventory_data="$inventory_data
"
                    ;;
            esac
            
            ((app_count++))
        fi
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Générer rapport final
    local total_size_human=$(echo "scale=2; $total_size_bytes / 1024 / 1024 / 1024" | bc 2>/dev/null || echo "inconnue")
    
    case "$output_format" in
        "json")
            local final_report="{
                \"metadonnees_rapport\": {
                    \"horodatage\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
                    \"nom_hote\": \"$hostname\",
                    \"info_appareil\": \"$device_info\",
                    \"version_macos\": \"$macos_version\",
                    \"utilisateur_actuel\": \"$current_user\",
                    \"total_apps\": $app_count,
                    \"taille_totale_octets\": $total_size_bytes,
                    \"taille_totale_gb\": \"$total_size_human GB\"
                },
                \"applications\": [$inventory_data]
            }"
            
            echo "$final_report" > "${report_file}.json"
            echo "✅ Rapport JSON sauvegardé dans : ${report_file}.json"
            ;;
            
        "csv")
            echo -e "$inventory_data" > "${report_file}.csv"
            echo "✅ Rapport CSV sauvegardé dans : ${report_file}.csv"
            ;;
            
        "text"|*)
            {
                echo "Rapport d'Inventaire App Store Roundfleet"
                echo "======================================="
                echo "Généré : $(date)"
                echo "Nom d'hôte : $hostname"
                echo "Appareil : $device_info"
                echo "Version macOS : $macos_version"
                echo "Utilisateur Actuel : $current_user"
                echo "Total Apps : $app_count"
                echo "Taille Totale : $total_size_human GB"
                echo ""
                echo "Applications :"
                echo "============="
                echo "$inventory_data"
            } > "${report_file}.txt"
            echo "✅ Rapport texte sauvegardé dans : ${report_file}.txt"
            ;;
    esac
    
    # Sortie résumé
    echo ""
    echo "=== Résumé Inventaire ==="
    echo "Apps découvertes : $app_count"
    echo "Taille totale : $total_size_human GB"
    echo "Format rapport : $output_format"
    echo "Emplacement rapport : $report_file"
    echo ""
    
    return $app_count
}

# Exemples d'utilisation
echo "📊 Gestion d'Inventaire App Store d'Entreprise"
echo ""
echo "1. Générer inventaire JSON avec métadonnées"
generate_app_store_inventory "json" "true" "/tmp"
echo ""

echo "2. Générer inventaire CSV (basique)"
generate_app_store_inventory "csv" "false" "/tmp"
echo ""

echo "3. Générer inventaire texte avec métadonnées"
generate_app_store_inventory "text" "true" "/tmp"

Analyse Conformité et Sécurité Applications

#!/bin/bash

# Analyse conformité et sécurité applications App Store
analyze_app_compliance() {
    echo "🔒 Analyse Conformité Applications App Store"
    echo "==========================================="
    echo ""
    
    local compliance_issues=0
    local security_concerns=0
    local policy_violations=0
    
    # Définir règles politique d'entreprise
    local blocked_apps=("Jeux" "Réseaux Sociaux" "Rencontres")  # Exemples catégories
    local required_apps=("Microsoft Word" "Microsoft Excel" "Slack")  # Exemples apps requises
    local max_app_age_days=365  # Apps plus anciennes que 1 an signalées
    local min_security_permissions=("Caméra" "Microphone" "Localisation")
    
    echo "Analyse applications App Store pour conformité..."
    echo ""
    
    # Suivre applications requises
    local found_required_apps=()
    local missing_required_apps=()
    
    # Analyser chaque application App Store
    while IFS= read -r -d '' app_path; do
        if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
            local app_name=$(basename "$app_path" .app)
            local bundle_id=""
            local version=""
            local category=""
            local install_date=""
            local days_since_install=""
            
            echo "Analyse : $app_name"
            
            # Obtenir métadonnées application
            if [[ -f "$app_path/Contents/Info.plist" ]]; then
                bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "inconnu")
                version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "inconnue")
                category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "inconnue")
            fi
            
            # Obtenir date installation et calculer âge
            if [[ -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
                install_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$app_path/Contents/_MASReceipt/receipt" 2>/dev/null || echo "inconnue")
                if [[ "$install_date" != "inconnue" ]]; then
                    local install_epoch=$(date -j -f "%Y-%m-%d" "$install_date" "+%s" 2>/dev/null || echo "0")
                    local current_epoch=$(date "+%s")
                    days_since_install=$(( (current_epoch - install_epoch) / 86400 ))
                fi
            fi
            
            # Vérifier contre applications/catégories bloquées
            local is_blocked=false
            for blocked_category in "${blocked_apps[@]}"; do
                if [[ "$category" =~ "$blocked_category" ]] || [[ "$app_name" =~ "$blocked_category" ]]; then
                    echo "  ❌ VIOLATION POLITIQUE : Catégorie app '$category' est bloquée"
                    is_blocked=true
                    ((policy_violations++))
                    break
                fi
            done
            
            # Vérifier âge application
            if [[ -n "$days_since_install" && "$days_since_install" -gt "$max_app_age_days" ]]; then
                echo "  ⚠️ CONFORMITÉ : App plus ancienne que $max_app_age_days jours ($days_since_install jours)"
                ((compliance_issues++))
            fi
            
            # Vérifier permissions sécurité
            local permission_count=0
            if [[ -f "$app_path/Contents/Info.plist" ]]; then
                if defaults read "$app_path/Contents/Info.plist" NSCameraUsageDescription >/dev/null 2>&1; then
                    echo "  🔒 SÉCURITÉ : App demande accès caméra"
                    ((permission_count++))
                fi
                
                if defaults read "$app_path/Contents/Info.plist" NSMicrophoneUsageDescription >/dev/null 2>&1; then
                    echo "  🔒 SÉCURITÉ : App demande accès microphone"
                    ((permission_count++))
                fi
                
                if defaults read "$app_path/Contents/Info.plist" NSLocationUsageDescription >/dev/null 2>&1; then
                    echo "  🔒 SÉCURITÉ : App demande accès localisation"
                    ((permission_count++))
                fi
                
                if [[ "$permission_count" -gt 2 ]]; then
                    echo "  ⚠️ PRÉOCCUPATION SÉCURITÉ : App demande permissions sensibles multiples"
                    ((security_concerns++))
                fi
            fi
            
            # Vérifier contre applications requises
            for required_app in "${required_apps[@]}"; do
                if [[ "$app_name" =~ "$required_app" ]]; then
                    found_required_apps+=("$required_app")
                fi
            done
            
            # Vérification signature code
            if command -v codesign >/dev/null 2>&1; then
                if ! codesign -v "$app_path" >/dev/null 2>&1; then
                    echo "  ❌ SÉCURITÉ : Signature code invalide"
                    ((security_concerns++))
                fi
            fi
            
            echo "  ✅ Analyse terminée"
            echo ""
        fi
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Vérifier applications requises manquantes
    for required_app in "${required_apps[@]}"; do
        local found=false
        for found_app in "${found_required_apps[@]}"; do
            if [[ "$found_app" == "$required_app" ]]; then
                found=true
                break
            fi
        done
        
        if [[ "$found" == "false" ]]; then
            missing_required_apps+=("$required_app")
        fi
    done
    
    # Générer rapport conformité
    echo "=== Rapport Analyse Conformité ==="
    echo "Violations politique : $policy_violations"
    echo "Problèmes conformité : $compliance_issues"
    echo "Préoccupations sécurité : $security_concerns"
    echo ""
    
    if [[ ${#missing_required_apps[@]} -gt 0 ]]; then
        echo "Applications requises manquantes :"
        for missing_app in "${missing_required_apps[@]}"; do
            echo "  - $missing_app"
        done
        echo ""
    fi
    
    if [[ ${#found_required_apps[@]} -gt 0 ]]; then
        echo "Applications requises trouvées :"
        for found_app in "${found_required_apps[@]}"; do
            echo "  ✅ $found_app"
        done
        echo ""
    fi
    
    # Score conformité global
    local total_issues=$((policy_violations + compliance_issues + security_concerns + ${#missing_required_apps[@]}))
    if [[ "$total_issues" -eq 0 ]]; then
        echo "🎉 STATUT CONFORMITÉ : ENTIÈREMENT CONFORME"
    elif [[ "$total_issues" -le 3 ]]; then
        echo "⚠️ STATUT CONFORMITÉ : PROBLÈMES MINEURS ($total_issues problèmes)"
    else
        echo "❌ STATUT CONFORMITÉ : PROBLÈMES MAJEURS ($total_issues problèmes)"
    fi
    
    return $total_issues
}

# Exécuter analyse conformité
analyze_app_compliance

Gestion Flotte et Rapports

Gestion Applications Flotte d'Entreprise

#!/bin/bash

# Gestion App Store flotte d'entreprise
manage_fleet_app_inventory() {
    local operation="${1:-discover}"  # discover, report, compliance, update
    local fleet_config_file="${2:-/etc/roundfleet/app_config.json}"
    local output_dir="${3:-/var/log/roundfleet}"
    
    echo "🚀 Gestion App Store Entreprise Roundfleet"
    echo "======================================="
    echo "Opération : $operation"
    echo "Fichier config : $fleet_config_file"
    echo "Répertoire sortie : $output_dir"
    echo ""
    
    # Assurer que répertoire sortie existe
    mkdir -p "$output_dir"
    
    # Identification appareil
    local device_id=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F': ' '{print $2}' | xargs)
    local device_name=$(hostname)
    local timestamp=$(date +"%Y%m%d_%H%M%S")
    local report_file="$output_dir/fleet_app_report_${device_id}_${timestamp}.json"
    
    case "$operation" in
        "discover")
            echo "🔍 Mode Découverte Flotte"
            echo "========================="
            
            # Générer inventaire application complet
            local app_data=$(generate_comprehensive_app_data)
            
            # Créer rapport flotte
            local fleet_report="{
                \"info_appareil\": {
                    \"id_appareil\": \"$device_id\",
                    \"nom_appareil\": \"$device_name\",
                    \"horodatage\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\",
                    \"version_macos\": \"$(sw_vers -productVersion)\",
                    \"utilisateur_actuel\": \"$(stat -f%Su /dev/console 2>/dev/null || echo "$USER")\"
                },
                \"inventaire_apps\": $app_data,
                \"operation\": \"decouverte_flotte\"
            }"
            
            echo "$fleet_report" > "$report_file"
            echo "✅ Rapport découverte flotte sauvegardé : $report_file"
            ;;
            
        "compliance")
            echo "📋 Vérification Conformité Flotte"
            echo "================================="
            
            # Exécuter analyse conformité
            local compliance_result=$(analyze_fleet_compliance)
            
            # Créer rapport conformité
            local compliance_report="{
                \"info_appareil\": {
                    \"id_appareil\": \"$device_id\",
                    \"nom_appareil\": \"$device_name\",
                    \"horodatage\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\"
                },
                \"resultats_conformite\": $compliance_result,
                \"operation\": \"verification_conformite\"
            }"
            
            echo "$compliance_report" > "$report_file"
            echo "✅ Rapport conformité sauvegardé : $report_file"
            ;;
            
        "report")
            echo "📊 Mode Rapports Flotte"
            echo "======================="
            
            # Générer tous formats rapport
            echo "Génération rapports flotte complets..."
            
            generate_app_store_inventory "json" "true" "$output_dir"
            generate_app_store_inventory "csv" "true" "$output_dir"
            generate_app_store_inventory "text" "true" "$output_dir"
            
            echo "✅ Tous rapports flotte générés dans : $output_dir"
            ;;
            
        "update")
            echo "🔄 Vérification Mise à Jour Flotte"
            echo "==================================="
            
            # Vérifier mises à jour applications
            check_app_store_updates
            ;;
            
        *)
            echo "❌ Opération inconnue : $operation"
            echo "Opérations disponibles : discover, report, compliance, update"
            return 1
            ;;
    esac
    
    return 0
}

# Fonction auxiliaire pour générer données applications complètes
generate_comprehensive_app_data() {
    local apps_json="["
    local first_app=true
    
    while IFS= read -r -d '' app_path; do
        if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
            local app_name=$(basename "$app_path" .app)
            local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "inconnu")
            local version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "inconnue")
            local size_bytes=$(du -sk "$app_path" 2>/dev/null | cut -f1 || echo "0")
            size_bytes=$((size_bytes * 1024))
            
            if [[ "$first_app" == "false" ]]; then
                apps_json="$apps_json,"
            fi
            
            apps_json="$apps_json{
                \"nom\": \"$app_name\",
                \"bundle_id\": \"$bundle_id\",
                \"version\": \"$version\",
                \"taille_octets\": $size_bytes,
                \"chemin\": \"$app_path\"
            }"
            
            first_app=false
        fi
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    apps_json="$apps_json]"
    echo "$apps_json"
}

# Vérifier mises à jour App Store
check_app_store_updates() {
    echo "Vérification mises à jour App Store disponibles..."
    
    # Utiliser softwareupdate pour vérifier mises à jour disponibles
    local updates_available=$(softwareupdate -l 2>/dev/null | grep -i "app store" || echo "")
    
    if [[ -n "$updates_available" ]]; then
        echo "📦 Mises à jour App Store disponibles :"
        echo "$updates_available"
    else
        echo "✅ Toutes applications App Store sont à jour"
    fi
    
    # Vérifier aussi Mac App Store directement si disponible
    if command -v mas >/dev/null 2>&1; then
        echo ""
        echo "Vérification avec mas-cli..."
        mas outdated 2>/dev/null || echo "mas-cli non disponible ou aucune mise à jour trouvée"
    fi
}

# Exemples d'utilisation
echo "Exemples Gestion Flotte :"
echo "========================="
echo ""

echo "1. Mode découverte :"
manage_fleet_app_inventory "discover"
echo ""

echo "2. Vérification conformité :"
manage_fleet_app_inventory "compliance"
echo ""

echo "3. Générer tous rapports :"
manage_fleet_app_inventory "report"

Intégration App Store Connect

Gestion Applications d'Entreprise avec App Store Connect

#!/bin/bash

# Intégration App Store Connect d'entreprise pour gestion licences
manage_app_store_licenses() {
    echo "📄 Gestion Licences App Store Connect"
    echo "====================================="
    echo ""
    
    # Note : Ceci nécessite accès App Store Connect d'entreprise
    # et configuration appropriée identifiants API
    
    local license_report_file="/tmp/app_store_licenses_$(date +%Y%m%d_%H%M%S).json"
    
    echo "Analyse licences applications App Store..."
    echo ""
    
    # Suivre applications nécessitant potentiellement licences business
    local business_apps=()
    local consumer_apps=()
    local unknown_apps=()
    
    while IFS= read -r -d '' app_path; do
        if [[ -d "$app_path" && -f "$app_path/Contents/_MASReceipt/receipt" ]]; then
            local app_name=$(basename "$app_path" .app)
            local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "inconnu")
            
            # Catégories nécessitant typiquement licences business
            local business_categories=("Outils Développeur" "Business" "Productivité" "Graphisme & Design")
            local is_business_app=false
            
            # Vérifier si application est orientée business
            if [[ -f "$app_path/Contents/Info.plist" ]]; then
                local category=$(defaults read "$app_path/Contents/Info.plist" LSApplicationCategoryType 2>/dev/null || echo "inconnue")
                
                for biz_cat in "${business_categories[@]}"; do
                    if [[ "$category" =~ "$biz_cat" ]]; then
                        is_business_app=true
                        break
                    fi
                done
                
                # Vérifier aussi modèles applications business communes
                if [[ "$app_name" =~ (Microsoft|Adobe|Slack|Zoom|Teams|Office) ]]; then
                    is_business_app=true
                fi
            fi
            
            if [[ "$is_business_app" == "true" ]]; then
                business_apps+=("$app_name ($bundle_id)")
                echo "💼 Application business détectée : $app_name"
            else
                # Applications consommateur potentiellement acceptables
                if [[ "$app_name" =~ (Calculatrice|TextEdit|Safari|Mail|Photos) ]]; then
                    consumer_apps+=("$app_name ($bundle_id)")
                    echo "👤 Application consommateur : $app_name"
                else
                    unknown_apps+=("$app_name ($bundle_id)")
                    echo "❓ Catégorie inconnue : $app_name"
                fi
            fi
        fi
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Générer rapport conformité licence
    {
        echo "{"
        echo "  \"analyse_licence\": {"
        echo "    \"horodatage\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\","
        echo "    \"id_appareil\": \"$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F': ' '{print $2}' | xargs)\","
        echo "    \"apps_business\": ["
        
        local first=true
        for app in "${business_apps[@]}"; do
            if [[ "$first" == "false" ]]; then echo ","; fi
            echo "      \"$app\""
            first=false
        done
        
        echo "    ],"
        echo "    \"apps_consommateur\": ["
        
        first=true
        for app in "${consumer_apps[@]}"; do
            if [[ "$first" == "false" ]]; then echo ","; fi
            echo "      \"$app\""
            first=false
        done
        
        echo "    ],"
        echo "    \"apps_inconnues\": ["
        
        first=true
        for app in "${unknown_apps[@]}"; do
            if [[ "$first" == "false" ]]; then echo ","; fi
            echo "      \"$app\""
            first=false
        done
        
        echo "    ],"
        echo "    \"resume\": {"
        echo "      \"total_apps_business\": ${#business_apps[@]},"
        echo "      \"total_apps_consommateur\": ${#consumer_apps[@]},"
        echo "      \"total_apps_inconnues\": ${#unknown_apps[@]},"
        echo "      \"necessite_revision_licence\": $([[ ${#business_apps[@]} -gt 0 || ${#unknown_apps[@]} -gt 0 ]] && echo "true" || echo "false")"
        echo "    }"
        echo "  }"
        echo "}"
    } > "$license_report_file"
    
    echo ""
    echo "=== Résumé Analyse Licence ==="
    echo "Applications business trouvées : ${#business_apps[@]}"
    echo "Applications consommateur trouvées : ${#consumer_apps[@]}"
    echo "Applications inconnues trouvées : ${#unknown_apps[@]}"
    echo ""
    
    if [[ ${#business_apps[@]} -gt 0 || ${#unknown_apps[@]} -gt 0 ]]; then
        echo "⚠️ Révision licence requise pour applications business/inconnues"
        echo "📄 Rapport licence sauvegardé : $license_report_file"
    else
        echo "✅ Aucune préoccupation licence business détectée"
    fi
    
    return 0
}

# Exécuter gestion licence
manage_app_store_licenses

Notes Importantes

Fonctionnalités Gestion Entreprise

  • Inventaire Complet - Découverte et suivi complets applications App Store
  • Surveillance Conformité - Application politique et analyse sécurité
  • Gestion Licence - Intégration App Store Connect d'entreprise
  • Rapports Flotte - Rapports multi-format (JSON, CSV, texte) avec métadonnées
  • Analyse Sécurité - Audit permissions et vérification signature code
  • Gestion Mise à Jour - Détection et gestion mises à jour App Store

Système Reçu App Store

  • Reçus MAS - Preuve numérique achat App Store située dans Contents/_MASReceipt/receipt
  • Identification Bundle - Suivi application unique via CFBundleIdentifier
  • Suivi Version - Gestion version application et numéro build
  • Métadonnées Installation - Suivi date installation et modification
  • Vérification Licence - Conformité et allocation licence d'entreprise

Sécurité et Conformité

  • Audit Permissions - Surveillance accès caméra, microphone, localisation
  • Vérification Signature Code - Valider intégrité et authenticité application
  • Application Politique - Validation catégories applications bloquées et applications requises
  • Analyse Âge - Identifier applications obsolètes nécessitant mises à jour
  • Suivi Identifiant Équipe - Identification équipe développeur pour politiques entreprise

Exemples d'Utilisation

# Découverte basique applications App Store
find /Applications -path '*Contents/_MASReceipt/receipt' -maxdepth 4 -print | \
    sed 's#.app/Contents/_MASReceipt/receipt#.app#g; s#/Applications/##'

# Inventaire entreprise avec sortie JSON
generate_app_store_inventory "json" "true" "/tmp"

# Analyse conformité
analyze_app_compliance

# Gestion flotte - mode découverte
manage_fleet_app_inventory "discover"

# Gestion licence
manage_app_store_licenses

Gestion des Mises à Jour Automatiques de l'App Store sur macOS

Contrôlez et gérez les mises à jour automatiques de l'App Store sur vos appareils Roundfleet pour optimiser l'utilisation de la bande passante, gérer les mises à jour de sécurité et maintenir la stabilité du système. Ce tutoriel couvre les politiques de mise à jour, la configuration d'entreprise et les stratégies complètes de gestion des mises à jour.

Comprendre les Mises à Jour Automatiques de l'App Store macOS

Les mises à jour automatiques de l'App Store sur macOS téléchargent et installent automatiquement les mises à jour d'applications depuis le Mac App Store. Cette fonctionnalité affecte :

  • Mises à Jour d'Applications - Installation automatique des mises à jour d'applications
  • Stockage Système - Les mises à jour téléchargées consomment de l'espace disque
  • Bande Passante Réseau - Les mises à jour se téléchargent en arrière-plan
  • Stabilité Système - Les nouvelles mises à jour peuvent introduire des bugs ou des problèmes de compatibilité

Considérations d'Entreprise

La gestion des mises à jour automatiques est cruciale pour les environnements d'entreprise :

  • Contrôle de la Bande Passante - Prévenir l'utilisation réseau inattendue
  • Gestion de la Sécurité - Contrôler quand les mises à jour de sécurité sont appliquées
  • Stabilité Système - Tester les mises à jour avant le déploiement
  • Gestion du Stockage - Prévenir les problèmes de stockage sur les appareils à espace limité
  • Exigences de Conformité - Certaines industries nécessitent un déploiement contrôlé des mises à jour

Contrôle de Base des Mises à Jour de l'App Store

Désactiver les Mises à Jour Automatiques

#!/bin/bash

# Désactiver les mises à jour automatiques de l'App Store
sudo defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE

echo "Mises à jour automatiques de l'App Store désactivées"
exit 0

Activer les Mises à Jour Automatiques

#!/bin/bash

# Activer les mises à jour automatiques de l'App Store
sudo defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool TRUE

echo "Mises à jour automatiques de l'App Store activées"
exit 0

Vérifier le Statut Actuel des Mises à Jour Automatiques

#!/bin/bash

# Vérifier le paramètre actuel de mise à jour automatique
auto_update_status=$(defaults read /Library/Preferences/com.apple.commerce.plist AutoUpdate 2>/dev/null || echo "Non Défini")

if [[ "$auto_update_status" == "1" ]]; then
    echo "Mises à Jour Automatiques de l'App Store : ACTIVÉES"
elif [[ "$auto_update_status" == "0" ]]; then
    echo "Mises à Jour Automatiques de l'App Store : DÉSACTIVÉES"
else
    echo "Mises à Jour Automatiques de l'App Store : PAR DÉFAUT (généralement activées)"
fi

Gestion Avancée des Mises à Jour

Configuration Complète de Politique de Mise à Jour

#!/bin/bash

# Gestion avancée des mises à jour de l'App Store avec validation
configure_app_store_updates() {
    local policy="$1"
    local schedule="$2"
    local dry_run="${3:-false}"
    
    # Valider les privilèges administrateur
    if [[ $EUID -ne 0 ]]; then
        echo "Erreur : Ce script nécessite des privilèges administrateur"
        echo "Veuillez exécuter avec sudo : sudo $0"
        exit 1
    fi
    
    echo "=== Configuration de la Politique de Mise à Jour de l'App Store : $policy ==="
    
    if [[ "$dry_run" == "true" ]]; then
        echo "MODE TEST - Aucun changement ne sera appliqué"
        return 0
    fi
    
    case "$policy" in
        "enterprise_controlled")
            echo "Application de la politique de mise à jour contrôlée d'entreprise..."
            
            # Désactiver les mises à jour automatiques pour un environnement contrôlé
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            
            # Désactiver le téléchargement automatique des mises à jour
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
            
            # Désactiver l'installation des mises à jour critiques
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool FALSE
            
            echo "✓ Politique contrôlée d'entreprise appliquée"
            ;;
        "security_only")
            echo "Application de la politique de mise à jour sécurité uniquement..."
            
            # Désactiver les mises à jour générales d'applications
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            
            # Activer uniquement les mises à jour de sécurité critiques
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool TRUE
            
            echo "✓ Politique sécurité uniquement appliquée"
            ;;
        "scheduled_updates")
            echo "Application de la politique de mise à jour programmée..."
            
            # Désactiver les mises à jour immédiates
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            
            # Configurer la vérification programmée des mises à jour
            setup_scheduled_updates "$schedule"
            
            echo "✓ Politique de mise à jour programmée appliquée"
            ;;
        "bandwidth_conscious")
            echo "Application de la politique de mise à jour consciente de la bande passante..."
            
            # Désactiver les téléchargements automatiques
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
            
            # Activer la vérification des mises à jour mais pas l'installation automatique
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            
            echo "✓ Politique consciente de la bande passante appliquée"
            ;;
        "full_auto")
            echo "Application de la politique de mise à jour entièrement automatique..."
            
            # Activer toutes les mises à jour automatiques
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool TRUE
            
            echo "✓ Politique de mise à jour entièrement automatique appliquée"
            ;;
        "disabled")
            echo "Désactivation de toutes les mises à jour automatiques..."
            
            # Désactiver toutes les fonctionnalités de mise à jour automatique
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool FALSE
            
            echo "✓ Toutes les mises à jour automatiques désactivées"
            ;;
        *)
            echo "Erreur : Politique inconnue '$policy'"
            echo "Politiques disponibles : enterprise_controlled, security_only, scheduled_updates, bandwidth_conscious, full_auto, disabled"
            return 1
            ;;
    esac
    
    # Vérifier la configuration
    verify_update_settings
}

# Vérifier les paramètres actuels de mise à jour
verify_update_settings() {
    echo ""
    echo "=== Configuration Actuelle des Mises à Jour ==="
    
    # Vérifier les mises à jour automatiques de l'App Store
    local app_store_auto=$(defaults read /Library/Preferences/com.apple.commerce.plist AutoUpdate 2>/dev/null || echo "Défaut")
    echo "Mises à Jour Automatiques App Store : $([ "$app_store_auto" == "1" ] && echo "Activées" || [ "$app_store_auto" == "0" ] && echo "Désactivées" || echo "Défaut (Activées)")"
    
    # Vérifier les paramètres de Software Update
    local auto_download=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload 2>/dev/null || echo "Défaut")
    echo "Téléchargement Automatique : $([ "$auto_download" == "1" ] && echo "Activé" || [ "$auto_download" == "0" ] && echo "Désactivé" || echo "Défaut")"
    
    local auto_check=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled 2>/dev/null || echo "Défaut")
    echo "Vérification Automatique : $([ "$auto_check" == "1" ] && echo "Activée" || [ "$auto_check" == "0" ] && echo "Désactivée" || echo "Défaut")"
    
    local critical_updates=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall 2>/dev/null || echo "Défaut")
    echo "Mises à Jour Critiques : $([ "$critical_updates" == "1" ] && echo "Activées" || [ "$critical_updates" == "0" ] && echo "Désactivées" || echo "Défaut")"
}

# Exemples d'utilisation
configure_app_store_updates "enterprise_controlled" "weekly"

Système de Gestion des Mises à Jour d'Entreprise App Store

#!/bin/bash

# Outil de Gestion des Mises à Jour de l'App Store Roundfleet
# Gestion complète des politiques de mise à jour et surveillance pour les appareils de flotte

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_appstore_updates.log"
REPORT_DIR="/etc/roundfleet/reports/updates"
CONFIG_DIR="/etc/roundfleet/updates"
POLICY_DIR="/etc/roundfleet/policies/updates"

# Créer les répertoires s'ils n'existent pas
mkdir -p "$REPORT_DIR" "$CONFIG_DIR" "$POLICY_DIR"

# Modèles de politiques de mise à jour
declare -A UPDATE_POLICIES=(
    ["enterprise_strict"]="app_updates_disabled,system_updates_manual,security_updates_auto,bandwidth_priority_high"
    ["enterprise_balanced"]="app_updates_scheduled,system_updates_auto,security_updates_immediate,bandwidth_priority_medium"
    ["enterprise_liberal"]="app_updates_auto,system_updates_auto,security_updates_immediate,bandwidth_priority_low"
    ["kiosk_mode"]="app_updates_disabled,system_updates_disabled,security_updates_manual,bandwidth_priority_high"
    ["development"]="app_updates_auto,system_updates_prompt,security_updates_auto,bandwidth_priority_low"
    ["education"]="app_updates_scheduled,system_updates_scheduled,security_updates_auto,bandwidth_priority_medium"
    ["healthcare"]="app_updates_manual,system_updates_manual,security_updates_immediate,bandwidth_priority_high"
    ["financial"]="app_updates_disabled,system_updates_manual,security_updates_immediate,bandwidth_priority_high"
    ["retail"]="app_updates_scheduled,system_updates_auto,security_updates_auto,bandwidth_priority_medium"
    ["remote_work"]="app_updates_auto,system_updates_prompt,security_updates_auto,bandwidth_priority_medium"
)

# Plannings de mise à jour pour différents scénarios
declare -A UPDATE_SCHEDULES=(
    ["business_hours"]="weekdays_evening,09:00-17:00_block"
    ["maintenance_window"]="weekend_only,saturday_2am"
    ["off_peak"]="overnight,02:00-05:00"
    ["immediate"]="real_time,no_delay"
    ["weekly_batch"]="sunday_night,sunday_23:00"
    ["monthly_patch"]="first_sunday,monthly_02:00"
)

# Profils de gestion de bande passante
declare -A BANDWIDTH_PROFILES=(
    ["conservative"]="max_5mbps,off_peak_only,cellular_disabled"
    ["balanced"]="max_20mbps,business_hours_limited,cellular_security_only"
    ["unlimited"]="no_throttle,anytime,cellular_enabled"
    ["emergency_only"]="max_1mbps,security_updates_only,cellular_emergency"
)

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

# Application avancée des politiques de mise à jour
enforce_update_policy() {
    local policy_name="$1"
    local environment_type="${2:-enterprise}"
    local bandwidth_profile="${3:-balanced}"
    local dry_run="${4:-false}"
    
    log_action "Application de la politique de mise à jour : $policy_name (environnement : $environment_type, bande passante : $bandwidth_profile, dry_run : $dry_run)"
    
    if [[ -z "${UPDATE_POLICIES[$policy_name]}" ]]; then
        log_action "ERREUR : Politique inconnue '$policy_name'"
        echo "Politiques disponibles : ${!UPDATE_POLICIES[*]}"
        return 1
    fi
    
    # Analyser la configuration de politique
    IFS=',' read -ra POLICY_PARTS <<< "${UPDATE_POLICIES[$policy_name]}"
    local app_updates="${POLICY_PARTS[0]}"
    local system_updates="${POLICY_PARTS[1]}"
    local security_updates="${POLICY_PARTS[2]}"
    local bandwidth_priority="${POLICY_PARTS[3]}"
    
    echo "=== Application de la Politique de Mise à Jour : $policy_name ==="
    echo "Mises à Jour d'Applications : $app_updates"
    echo "Mises à Jour Système : $system_updates"
    echo "Mises à Jour de Sécurité : $security_updates"
    echo "Priorité Bande Passante : $bandwidth_priority"
    echo "Environnement : $environment_type"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "MODE TEST - Aucun changement ne sera appliqué"
        return 0
    fi
    
    # Appliquer les paramètres de mise à jour d'applications
    apply_app_update_policy "$app_updates"
    
    # Appliquer les paramètres de mise à jour système
    apply_system_update_policy "$system_updates"
    
    # Appliquer les paramètres de mise à jour de sécurité
    apply_security_update_policy "$security_updates"
    
    # Appliquer la gestion de bande passante
    apply_bandwidth_management "$bandwidth_profile"
    
    # Configurer les paramètres spécifiques à l'environnement
    configure_environment_settings "$environment_type"
    
    # Générer un rapport de conformité de politique
    local report_file="$REPORT_DIR/policy_enforcement_${policy_name}_$(date +%Y%m%d_%H%M%S).json"
    generate_comprehensive_report "$policy_name" "$report_file"
    
    log_action "Application de politique de mise à jour terminée : $report_file"
    echo "$report_file"
}

# Appliquer les paramètres de politique de mise à jour d'applications
apply_app_update_policy() {
    local policy="$1"
    
    case "$policy" in
        "app_updates_disabled")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            echo "✓ Mises à jour automatiques de l'App Store désactivées"
            ;;
        "app_updates_auto")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool TRUE
            echo "✓ Mises à jour automatiques de l'App Store activées"
            ;;
        "app_updates_scheduled")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            setup_scheduled_app_updates "weekly"
            echo "✓ Mises à jour de l'App Store programmées pour la fenêtre de maintenance hebdomadaire"
            ;;
        "app_updates_manual")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            echo "✓ Mises à jour de l'App Store définies en manuel avec vérification automatique"
            ;;
    esac
}

# Appliquer les paramètres de politique de mise à jour système
apply_system_update_policy() {
    local policy="$1"
    
    case "$policy" in
        "system_updates_disabled")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool FALSE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
            echo "✓ Mises à jour système complètement désactivées"
            ;;
        "system_updates_auto")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool TRUE
            echo "✓ Mises à jour système entièrement automatisées"
            ;;
        "system_updates_manual")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
            echo "✓ Mises à jour système définies en installation manuelle"
            ;;
        "system_updates_prompt")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool TRUE
            # Configurer les invites utilisateur pour l'installation
            echo "✓ Mises à jour système définies pour inviter l'utilisateur à l'installation"
            ;;
        "system_updates_scheduled")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool TRUE
            setup_scheduled_system_updates "monthly"
            echo "✓ Mises à jour système programmées pour la maintenance mensuelle"
            ;;
    esac
}

# Appliquer les paramètres de politique de mise à jour de sécurité
apply_security_update_policy() {
    local policy="$1"
    
    case "$policy" in
        "security_updates_immediate")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool TRUE
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
            echo "✓ Mises à jour de sécurité définies en installation immédiate"
            ;;
        "security_updates_auto")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool TRUE
            echo "✓ Mises à jour de sécurité activées pour installation automatique"
            ;;
        "security_updates_manual")
            defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool FALSE
            echo "✓ Mises à jour de sécurité définies en installation manuelle"
            ;;
    esac
}

# Surveiller la conformité des mises à jour à travers la flotte
monitor_fleet_update_compliance() {
    local compliance_type="${1:-standard}"
    
    echo "=== Moniteur de Conformité des Mises à Jour de Flotte ==="
    
    # Vérifier le statut global de conformité
    local policy_violations=0
    local total_checks=0
    
    # Vérifier les paramètres de l'App Store
    local app_store_setting=$(defaults read /Library/Preferences/com.apple.commerce.plist AutoUpdate 2>/dev/null || echo "default")
    ((total_checks++))
    
    # Vérifier les mises à jour en attente qui violent la politique
    local pending_updates=$(softwareupdate -l 2>/dev/null | grep -c "recommended" || echo "0")
    
    if [[ "$pending_updates" -gt 0 && "$compliance_type" == "strict" ]]; then
        ((policy_violations++))
        echo "⚠️ Violation de Politique : Mises à jour en attente trouvées en mode de conformité strict"
    fi
    
    # Calculer le score de conformité
    local compliance_score=$((100 - (policy_violations * 100 / total_checks)))
    
    echo "Score de Conformité : $compliance_score%"
    echo "Violations de Politique : $policy_violations"
    echo "Vérifications Totales : $total_checks"
    echo "Mises à Jour en Attente : $pending_updates"
}

# Fonction d'exécution principale
main() {
    local action="${1:-status}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Gestion des Mises à Jour de l'App Store Roundfleet Démarrée ==="
    log_action "Action : $action"
    
    # Assurer les privilèges requis pour les changements de configuration
    if [[ "$action" != "status" && "$action" != "help" && "$action" != "report" && $EUID -ne 0 ]]; then
        echo "Erreur : Cette action nécessite des privilèges administrateur"
        echo "Veuillez exécuter avec sudo : sudo $0 $*"
        exit 1
    fi
    
    case "$action" in
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Politiques disponibles : ${!UPDATE_POLICIES[*]}"
                exit 1
            fi
            enforce_update_policy "$param1" "$param2" "$param3" "$param4"
            ;;
        "enable")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool TRUE
            echo "✓ Mises à jour automatiques de l'App Store activées"
            ;;
        "disable")
            defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
            echo "✓ Mises à jour automatiques de l'App Store désactivées"
            ;;
        "check")
            echo "Vérification des mises à jour disponibles..."
            softwareupdate -l
            ;;
        "install")
            if [[ -n "$param1" ]]; then
                echo "Installation de la mise à jour spécifique : $param1"
                softwareupdate -i "$param1"
            else
                echo "Installation de toutes les mises à jour disponibles..."
                softwareupdate -i -a
            fi
            ;;
        "status")
            verify_update_settings
            ;;
        "compliance")
            monitor_fleet_update_compliance "$param1"
            ;;
        "reset")
            echo "Réinitialisation des paramètres de mise à jour de l'App Store aux valeurs par défaut..."
            defaults delete /Library/Preferences/com.apple.commerce.plist AutoUpdate 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall 2>/dev/null || true
            echo "✓ Paramètres de mise à jour réinitialisés aux valeurs système par défaut"
            ;;
        "help")
            echo "Usage : $0 [action] [options...]"
            echo "Actions :"
            echo "  policy <nom_politique> [environnement] [bande_passante] [dry_run] - Appliquer une politique de mise à jour"
            echo "  enable - Activer les mises à jour automatiques de l'App Store"
            echo "  disable - Désactiver les mises à jour automatiques de l'App Store"
            echo "  check - Vérifier les mises à jour disponibles"
            echo "  install [nom_mise_à_jour] - Installer les mises à jour (toutes ou spécifique)"
            echo "  status - Afficher la configuration actuelle des mises à jour"
            echo "  compliance [type] - Vérifier la conformité de la flotte"
            echo "  reset - Réinitialiser aux valeurs système par défaut"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Politiques : ${!UPDATE_POLICIES[*]}"
            echo "Plannings : ${!UPDATE_SCHEDULES[*]}"
            echo "Profils Bande Passante : ${!BANDWIDTH_PROFILES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion des mises à jour de l'App Store terminée ==="
}

# Exécuter la fonction principale
main "$@"

Sécurité et Conformité des Mises à Jour

Conformité Santé/HIPAA

#!/bin/bash

# Configurer la gestion des mises à jour conforme HIPAA
configure_hipaa_update_compliance() {
    echo "=== Configuration de la Conformité HIPAA des Mises à Jour ==="
    
    # Désactiver les mises à jour automatiques pour le contrôle de conformité
    defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
    defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
    
    # Activer uniquement les mises à jour de sécurité
    defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool TRUE
    
    # Configurer la journalisation d'audit
    setup_update_audit_logging "hipaa"
    
    echo "✓ Conformité HIPAA des mises à jour configurée"
}

configure_hipaa_update_compliance

Conformité Services Financiers

#!/bin/bash

# Configurer la conformité des mises à jour pour les services financiers
configure_financial_update_compliance() {
    echo "=== Configuration de la Conformité des Services Financiers ==="
    
    # Contrôle strict des mises à jour pour la conformité financière
    defaults write /Library/Preferences/com.apple.commerce.plist AutoUpdate -bool FALSE
    defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticDownload -bool FALSE
    defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist AutomaticCheckEnabled -bool TRUE
    
    # Mises à jour de sécurité uniquement avec approbation manuelle
    defaults write /Library/Preferences/com.apple.SoftwareUpdate.plist CriticalUpdateInstall -bool FALSE
    
    echo "✓ Conformité des services financiers configurée"
}

configure_financial_update_compliance

Dépannage et Maintenance

Vérification de l'État du Système de Mise à Jour

#!/bin/bash

# Vérification complète de l'état du système de mise à jour
perform_update_health_check() {
    echo "=== Vérification de l'État du Système de Mise à Jour ==="
    
    # Vérifier le statut du service de mise à jour
    local update_service_status
    update_service_status=$(launchctl list | grep -c "com.apple.softwareupdated" || echo "0")
    echo "Service de Mise à Jour Logicielle : $([ "$update_service_status" -gt 0 ] && echo "En Cours" || echo "Arrêté")"
    
    # Vérifier le cache de mise à jour
    local cache_path="/Library/Updates"
    if [[ -d "$cache_path" ]]; then
        local cache_size=$(du -sh "$cache_path" | cut -f1)
        local cache_files=$(find "$cache_path" -type f | wc -l | tr -d ' ')
        echo "Cache de Mise à Jour : $cache_size ($cache_files fichiers)"
    else
        echo "Cache de Mise à Jour : Non présent"
    fi
    
    # Vérifier les préférences corrompues
    local commerce_plist="/Library/Preferences/com.apple.commerce.plist"
    local softwareupdate_plist="/Library/Preferences/com.apple.SoftwareUpdate.plist"
    
    if plutil -lint "$commerce_plist" &>/dev/null; then
        echo "Préférences Commerce : Valides"
    else
        echo "⚠️ Préférences Commerce : Corrompues ou manquantes"
    fi
    
    if plutil -lint "$softwareupdate_plist" &>/dev/null; then
        echo "Préférences Software Update : Valides"
    else
        echo "⚠️ Préférences Software Update : Corrompues ou manquantes"
    fi
    
    # Vérifier la connectivité réseau pour les mises à jour
    if curl -s --connect-timeout 5 "https://swscan.apple.com/" &>/dev/null; then
        echo "Serveurs de Mise à Jour Apple : Accessibles"
    else
        echo "⚠️ Serveurs de Mise à Jour Apple : Non accessibles"
    fi
}

perform_update_health_check

Notes Importantes

  • Privilèges administrateur requis pour les changements de configuration de mise à jour
  • Exigences de redémarrage - Certains paramètres prennent effet après redémarrage
  • Impact réseau - Considérer l'utilisation de bande passante pour les mises à jour automatiques
  • Implications de sécurité - Équilibrer l'automatisation avec le contrôle de sécurité
  • Exigences de conformité - Certaines industries nécessitent une approbation manuelle des mises à jour
  • Considérations de stockage - Les mises à jour téléchargées consomment de l'espace disque
  • Recommandations de test - Tester les politiques de mise à jour sur des appareils de test d'abord
  • Importance de surveillance - La vérification régulière de conformité prévient la dérive de politique

Afficher l'heure de dernière ouverture des applications et fichiers sur macOS

Ce guide complet démontre comment suivre quand les applications et fichiers ont été accédés pour la dernière fois sur les appareils macOS, fournissant des informations essentielles pour la gestion du parc Mac et la surveillance d'utilisation.

Aperçu

La surveillance des modèles d'accès aux applications et fichiers est cruciale pour :

  • Optimisation des performances : Identifier les applications gourmandes en ressources
  • Gestion des licences : Suivre l'utilisation des logiciels pour la conformité
  • Audit de sécurité : Surveiller l'accès aux fichiers pour la conformité sécuritaire
  • Optimisation du stockage : Trouver les applications et fichiers inutilisés
  • Analyse comportementale : Comprendre les habitudes de travail et la productivité

Script de base pour l'heure de dernière ouverture

Vérification simple d'application/fichier

Créez un script de base pour vérifier quand une application ou un fichier a été ouvert pour la dernière fois :

#!/bin/bash

# Script de base pour obtenir l'heure de dernière ouverture d'une app ou fichier
# Usage: ./last_opened.sh "/chemin/vers/app/ou/fichier"

if [ $# -eq 0 ]; then
    echo "Usage: $0 <chemin_fichier>"
    echo "Exemple: $0 '/Applications/Safari.app'"
    exit 1
fi

file_path="$1"

# Vérifier si le fichier existe
if [ ! -e "$file_path" ]; then
    echo "Erreur: Fichier ou application non trouvé: $file_path"
    exit 1
fi

# Obtenir l'heure de dernière ouverture avec mdls
datetime=$(mdls "$file_path" -name kMDItemLastUsedDate | awk '{print $3,$4}')

if [ "$datetime" = "(null)" ]; then
    echo "'$file_path' n'a jamais été ouvert ou l'heure de dernière ouverture n'est pas disponible"
    exit 0
fi

echo "'$file_path' a été ouvert pour la dernière fois le (UTC):"
echo "$datetime"
echo "'$file_path' a été ouvert pour la dernière fois le (Heure locale):"
echo "$(date -jf "%Y-%m-%d %H:%M:%S %z" "$datetime +0000" +"%Y-%m-%d %H:%M:%S")"

Script amélioré avec gestion d'erreurs

#!/bin/bash

# Script amélioré avec gestion d'erreurs complète et formatage
# Usage: ./enhanced_last_opened.sh "/chemin/vers/app/ou/fichier"

check_last_opened() {
    local file_path="$1"
    local file_name=$(basename "$file_path")
    
    # Valider l'entrée
    if [ -z "$file_path" ]; then
        echo "Erreur: Aucun chemin de fichier fourni"
        return 1
    fi
    
    # Vérifier si le fichier existe
    if [ ! -e "$file_path" ]; then
        echo "Erreur: Fichier non trouvé: $file_path"
        return 1
    fi
    
    # Obtenir les métadonnées
    local datetime=$(mdls "$file_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
    local creation_date=$(mdls "$file_path" -name kMDItemContentCreationDate 2>/dev/null | awk '{print $3,$4}')
    local modification_date=$(mdls "$file_path" -name kMDItemContentModificationDate 2>/dev/null | awk '{print $3,$4}')
    
    echo "=== Informations du fichier ==="
    echo "Fichier: $file_name"
    echo "Chemin: $file_path"
    echo ""
    
    # Heure de dernière ouverture
    if [ "$datetime" = "(null)" ] || [ -z "$datetime" ]; then
        echo "Dernière ouverture: Jamais ouvert ou information non disponible"
    else
        echo "Dernière ouverture (UTC): $datetime"
        local local_time=$(date -jf "%Y-%m-%d %H:%M:%S %z" "$datetime +0000" +"%Y-%m-%d %H:%M:%S" 2>/dev/null)
        if [ $? -eq 0 ]; then
            echo "Dernière ouverture (Locale): $local_time"
        else
            echo "Dernière ouverture (Locale): Impossible de convertir l'heure"
        fi
    fi
    
    # Date de création
    if [ "$creation_date" != "(null)" ] && [ -n "$creation_date" ]; then
        echo "Créé (UTC): $creation_date"
    fi
    
    # Date de modification
    if [ "$modification_date" != "(null)" ] && [ -n "$modification_date" ]; then
        echo "Modifié (UTC): $modification_date"
    fi
    
    echo "=============================="
    echo ""
}

# Exécution principale
if [ $# -eq 0 ]; then
    echo "Usage: $0 <chemin_fichier>"
    echo "Exemple: $0 '/Applications/Safari.app'"
    exit 1
fi

check_last_opened "$1"

Surveillance avancée des applications

Scanner d'applications en lot

#!/bin/bash

# Scanner d'applications en lot avec rapport détaillé
# Usage: ./bulk_app_scanner.sh

scan_applications() {
    local output_file="rapport_usage_apps_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "Rapport d'utilisation des applications Roundfleet" > "$output_file"
    echo "Généré: $(date)" >> "$output_file"
    echo "Appareil: $(scutil --get ComputerName)" >> "$output_file"
    echo "Utilisateur: $(whoami)" >> "$output_file"
    echo "=======================================" >> "$output_file"
    echo "" >> "$output_file"
    
    # Scanner le dossier Applications
    echo "Scan de /Applications..."
    find /Applications -maxdepth 2 -name "*.app" -type d | while read app_path; do
        app_name=$(basename "$app_path" .app)
        
        # Obtenir l'heure de dernière ouverture
        datetime=$(mdls "$app_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
        
        if [ "$datetime" = "(null)" ] || [ -z "$datetime" ]; then
            last_opened="Jamais ouvert"
        else
            last_opened=$(date -jf "%Y-%m-%d %H:%M:%S %z" "$datetime +0000" +"%Y-%m-%d %H:%M:%S" 2>/dev/null)
            if [ $? -ne 0 ]; then
                last_opened="$datetime (UTC)"
            fi
        fi
        
        # Obtenir la version de l'app
        app_version=$(mdls "$app_path" -name kMDItemVersion 2>/dev/null | awk -F'"' '{print $2}')
        if [ "$app_version" = "(null)" ] || [ -z "$app_version" ]; then
            app_version="Inconnue"
        fi
        
        # Obtenir la taille de l'app
        app_size=$(du -sh "$app_path" 2>/dev/null | cut -f1)
        if [ -z "$app_size" ]; then
            app_size="Inconnue"
        fi
        
        echo "App: $app_name" >> "$output_file"
        echo "  Version: $app_version" >> "$output_file"
        echo "  Taille: $app_size" >> "$output_file"
        echo "  Dernière ouverture: $last_opened" >> "$output_file"
        echo "  Chemin: $app_path" >> "$output_file"
        echo "" >> "$output_file"
        
        # Indicateur de progression
        echo "Traité: $app_name"
    done
    
    echo "Rapport sauvegardé dans: $output_file"
}

# Exécuter le scan
scan_applications

Filtre des applications récemment utilisées

#!/bin/bash

# Filtrer les applications par utilisation récente
# Usage: ./recent_apps.sh [jours]

filter_recent_apps() {
    local days_threshold=${1:-7}  # Par défaut 7 jours
    local cutoff_date=$(date -v -${days_threshold}d +%Y-%m-%d)
    
    echo "Applications utilisées dans les $days_threshold derniers jours:"
    echo "Date limite: $cutoff_date"
    echo "=================================="
    
    find /Applications -maxdepth 2 -name "*.app" -type d | while read app_path; do
        app_name=$(basename "$app_path" .app)
        
        # Obtenir l'heure de dernière ouverture
        datetime=$(mdls "$app_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
        
        if [ "$datetime" != "(null)" ] && [ -n "$datetime" ]; then
            # Convertir en format comparable
            app_date=$(echo "$datetime" | cut -d' ' -f1)
            
            # Comparer les dates
            if [[ "$app_date" > "$cutoff_date" ]]; then
                local_time=$(date -jf "%Y-%m-%d %H:%M:%S %z" "$datetime +0000" +"%Y-%m-%d %H:%M:%S" 2>/dev/null)
                if [ $? -eq 0 ]; then
                    echo "$app_name - Dernière utilisation: $local_time"
                else
                    echo "$app_name - Dernière utilisation: $datetime (UTC)"
                fi
            fi
        fi
    done | sort
}

# Exécution principale
if [ $# -gt 1 ]; then
    echo "Usage: $0 [jours]"
    echo "Exemple: $0 30  # Afficher les apps utilisées dans les 30 derniers jours"
    exit 1
fi

filter_recent_apps "$1"

Surveillance des fichiers d'entreprise

Suivi d'accès aux documents

#!/bin/bash

# Suivre les modèles d'accès aux documents pour les types de fichiers courants
# Usage: ./document_tracker.sh "/chemin/vers/documents"

track_document_access() {
    local base_path=${1:-"$HOME/Documents"}
    local output_file="acces_documents_$(date +%Y%m%d_%H%M%S).json"
    
    echo "Suivi de l'accès aux documents dans: $base_path"
    
    # Créer le rapport JSON
    cat > "$output_file" << EOF
{
  "info_rapport": {
    "genere": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "appareil": "$(scutil --get ComputerName)",
    "utilisateur": "$(whoami)",
    "chemin_scan": "$base_path",
    "version_roundfleet": "1.0"
  },
  "documents": [
EOF
    
    local first_entry=true
    
    # Types de documents courants
    local file_types=("*.pdf" "*.doc" "*.docx" "*.xls" "*.xlsx" "*.ppt" "*.pptx" "*.txt" "*.rtf" "*.pages" "*.numbers" "*.keynote")
    
    for pattern in "${file_types[@]}"; do
        find "$base_path" -name "$pattern" -type f 2>/dev/null | while read file_path; do
            # Obtenir les métadonnées du fichier
            local filename=$(basename "$file_path")
            local extension="${filename##*.}"
            local size=$(stat -f%z "$file_path" 2>/dev/null || echo "0")
            
            # Obtenir les horodatages
            local last_used=$(mdls "$file_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
            local created=$(mdls "$file_path" -name kMDItemContentCreationDate 2>/dev/null | awk '{print $3,$4}')
            local modified=$(mdls "$file_path" -name kMDItemContentModificationDate 2>/dev/null | awk '{print $3,$4}')
            
            # Formater pour JSON
            if [ "$last_used" = "(null)" ] || [ -z "$last_used" ]; then
                last_used="null"
            else
                last_used="\"$last_used\""
            fi
            
            if [ "$created" = "(null)" ] || [ -z "$created" ]; then
                created="null"
            else
                created="\"$created\""
            fi
            
            if [ "$modified" = "(null)" ] || [ -z "$modified" ]; then
                modified="null"
            else
                modified="\"$modified\""
            fi
            
            # Ajouter une virgule si ce n'est pas la première entrée
            if [ "$first_entry" = false ]; then
                echo "," >> "$output_file"
            fi
            first_entry=false
            
            # Ajouter l'entrée du document
            cat >> "$output_file" << EOF
    {
      "nom_fichier": "$filename",
      "extension": "$extension",
      "taille_octets": $size,
      "chemin": "$file_path",
      "derniere_utilisation": $last_used,
      "cree": $created,
      "modifie": $modified
    }EOF
        done
    done
    
    # Fermer le JSON
    cat >> "$output_file" << EOF

  ]
}
EOF
    
    echo "Rapport d'accès aux documents sauvegardé dans: $output_file"
}

# Exécuter le suivi
track_document_access "$1"

Moniteur d'accès aux fichiers multi-utilisateurs

#!/bin/bash

# Surveiller l'accès aux fichiers sur plusieurs comptes utilisateurs
# Usage: ./multi_user_monitor.sh

monitor_multi_user_access() {
    local report_file="acces_multi_utilisateurs_$(date +%Y%m%d_%H%M%S).txt"
    
    echo "Rapport d'accès aux fichiers multi-utilisateurs Roundfleet" > "$report_file"
    echo "Généré: $(date)" >> "$report_file"
    echo "Appareil: $(scutil --get ComputerName)" >> "$report_file"
    echo "=========================================" >> "$report_file"
    echo "" >> "$report_file"
    
    # Obtenir tous les répertoires home des utilisateurs
    local users=($(dscl . -list /Users | grep -v "^_" | grep -v "daemon" | grep -v "nobody" | grep -v "root"))
    
    for user in "${users[@]}"; do
        local user_home=$(dscl . -read /Users/$user NFSHomeDirectory | awk '{print $2}')
        
        if [ -d "$user_home" ]; then
            echo "Utilisateur: $user ($user_home)" >> "$report_file"
            echo "--------------------------------" >> "$report_file"
            
            # Vérifier le dossier Documents
            if [ -d "$user_home/Documents" ]; then
                echo "Documents récemment accédés:" >> "$report_file"
                find "$user_home/Documents" -type f -name "*.pdf" -o -name "*.doc*" -o -name "*.xls*" -o -name "*.ppt*" 2>/dev/null | head -10 | while read file_path; do
                    local filename=$(basename "$file_path")
                    local last_used=$(mdls "$file_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
                    
                    if [ "$last_used" != "(null)" ] && [ -n "$last_used" ]; then
                        echo "  - $filename (Dernière utilisation: $last_used)" >> "$report_file"
                    fi
                done
            fi
            
            # Vérifier le dossier Téléchargements
            if [ -d "$user_home/Downloads" ]; then
                echo "Téléchargements récents:" >> "$report_file"
                find "$user_home/Downloads" -type f -mtime -7 2>/dev/null | head -5 | while read file_path; do
                    local filename=$(basename "$file_path")
                    local mod_time=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$file_path" 2>/dev/null)
                    echo "  - $filename (Téléchargé: $mod_time)" >> "$report_file"
                done
            fi
            
            echo "" >> "$report_file"
        fi
    done
    
    echo "Rapport d'accès multi-utilisateurs sauvegardé dans: $report_file"
}

# Exécuter la surveillance
monitor_multi_user_access

Gestion distante du parc

Collecteur d'utilisation centralisé

#!/bin/bash

# Collecter les données d'utilisation pour la gestion distante du parc
# Usage: ./fleet_collector.sh

collect_fleet_data() {
    local device_id=$(system_profiler SPHardwareDataType | grep "Hardware UUID" | awk '{print $3}')
    local computer_name=$(scutil --get ComputerName)
    local timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
    
    # Créer un rapport complet
    local report_file="utilisation_parc_${computer_name}_$(date +%Y%m%d_%H%M%S).json"
    
    cat > "$report_file" << EOF
{
  "info_appareil": {
    "id_appareil": "$device_id",
    "nom_ordinateur": "$computer_name",
    "horodatage": "$timestamp",
    "version_os": "$(sw_vers -productVersion)",
    "duree_fonctionnement": "$(uptime | awk '{print $3,$4}' | sed 's/,//')"
  },
  "utilisation_applications": [
EOF
    
    # Collecter les principales applications
    local first_app=true
    find /Applications -maxdepth 2 -name "*.app" -type d | head -20 | while read app_path; do
        local app_name=$(basename "$app_path" .app)
        local last_used=$(mdls "$app_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print $3,$4}')
        local version=$(mdls "$app_path" -name kMDItemVersion 2>/dev/null | awk -F'"' '{print $2}')
        
        if [ "$first_app" = false ]; then
            echo "," >> "$report_file"
        fi
        first_app=false
        
        # Formater les valeurs pour JSON
        if [ "$last_used" = "(null)" ] || [ -z "$last_used" ]; then
            last_used="null"
        else
            last_used="\"$last_used\""
        fi
        
        if [ "$version" = "(null)" ] || [ -z "$version" ]; then
            version="null"
        else
            version="\"$version\""
        fi
        
        cat >> "$report_file" << EOF
    {
      "nom": "$app_name",
      "version": $version,
      "derniere_utilisation": $last_used,
      "chemin": "$app_path"
    }EOF
    done
    
    cat >> "$report_file" << EOF

  ],
  "stats_systeme": {
    "total_applications": $(find /Applications -maxdepth 2 -name "*.app" -type d | wc -l | tr -d ' '),
    "utilisation_disque": "$(df -h / | tail -1 | awk '{print $5}')",
    "utilisation_memoire": "$(vm_stat | grep "Pages active" | awk '{print $3}' | sed 's/\.//')"
  }
}
EOF
    
    echo "Données du parc collectées dans: $report_file"
    
    # Optionnel: Envoyer au serveur central
    # curl -X POST -H "Content-Type: application/json" -d @"$report_file" "https://votre-serveur-parc.com/api/utilisation"
}

# Exécuter la collecte
collect_fleet_data

Surveillance automatisée de l'utilisation

#!/bin/bash

# Surveillance automatisée de l'utilisation avec alertes
# Usage: ./usage_monitor.sh

setup_monitoring() {
    local log_file="/var/log/roundfleet_usage.log"
    local config_file="/etc/roundfleet/usage_config.conf"
    
    # Créer la configuration si elle n'existe pas
    if [ ! -f "$config_file" ]; then
        sudo mkdir -p /etc/roundfleet
        sudo cat > "$config_file" << EOF
# Configuration de surveillance d'utilisation Roundfleet
MONITOR_INTERVAL=3600  # Vérifier toutes les heures
ALERT_THRESHOLD=30     # Alerter si app inutilisée pendant 30 jours
REPORT_INTERVAL=86400  # Générer rapport quotidien
CLEANUP_THRESHOLD=90   # Marquer les apps inutilisées pendant 90 jours
EOF
    fi
    
    # Charger la configuration
    source "$config_file"
    
    # Créer le script de surveillance
    cat > "/tmp/roundfleet_monitor.sh" << EOF
#!/bin/bash

# Moniteur d'utilisation Roundfleet
log_usage() {
    local timestamp=\$(date -u +%Y-%m-%dT%H:%M:%SZ)
    local computer_name=\$(scutil --get ComputerName)
    
    echo "[\$timestamp] Début de vérification d'utilisation sur \$computer_name" >> "$log_file"
    
    # Vérifier les applications inutilisées
    find /Applications -maxdepth 2 -name "*.app" -type d | while read app_path; do
        local app_name=\$(basename "\$app_path" .app)
        local last_used=\$(mdls "\$app_path" -name kMDItemLastUsedDate 2>/dev/null | awk '{print \$3,\$4}')
        
        if [ "\$last_used" != "(null)" ] && [ -n "\$last_used" ]; then
            local days_since=\$(( (\$(date +%s) - \$(date -jf "%Y-%m-%d %H:%M:%S %z" "\$last_used +0000" +%s)) / 86400 ))
            
            if [ \$days_since -gt $ALERT_THRESHOLD ]; then
                echo "[\$timestamp] ALERTE: \$app_name inutilisée pendant \$days_since jours" >> "$log_file"
            fi
            
            if [ \$days_since -gt $CLEANUP_THRESHOLD ]; then
                echo "[\$timestamp] NETTOYAGE: \$app_name marquée pour suppression (\$days_since jours)" >> "$log_file"
            fi
        fi
    done
    
    echo "[\$timestamp] Vérification d'utilisation terminée" >> "$log_file"
}

# Exécuter la surveillance
log_usage
EOF
    
    chmod +x "/tmp/roundfleet_monitor.sh"
    
    # Configurer launchd pour la surveillance automatisée
    cat > "/tmp/com.roundfleet.usage.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.roundfleet.usage.monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/tmp/roundfleet_monitor.sh</string>
    </array>
    <key>StartInterval</key>
    <integer>$MONITOR_INTERVAL</integer>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF
    
    echo "Configuration de surveillance terminée. Utilisez 'sudo launchctl load /tmp/com.roundfleet.usage.monitor.plist' pour démarrer."
}

# Exécuter la configuration
setup_monitoring

Meilleures pratiques pour la gestion du parc Mac

1. Optimisation des performances

  • Surveiller les applications gourmandes en ressources
  • Suivre les applications qui n'ont pas été utilisées récemment
  • Identifier les opportunités de nettoyage d'applications
  • Optimiser les performances système grâce aux informations d'utilisation

2. Sécurité et conformité

  • Suivre l'accès aux fichiers pour les audits de sécurité
  • Surveiller la conformité de gestion des documents
  • Identifier les modèles d'accès non autorisés aux fichiers
  • Maintenir les journaux d'accès pour les exigences de conformité

3. Gestion des licences

  • Surveiller l'utilisation des logiciels pour l'optimisation des licences
  • Suivre l'efficacité du déploiement d'applications
  • Identifier les licences inutilisées pour des économies de coût
  • Assurer la conformité aux accords de licence logicielle

4. Expérience utilisateur

  • Comprendre les modèles de comportement des utilisateurs
  • Optimiser les stratégies de déploiement d'applications
  • Améliorer la productivité des utilisateurs grâce aux informations d'utilisation
  • Personnaliser les configurations d'appareils basées sur l'utilisation

5. Maintenance et nettoyage

  • Identifier les applications inutilisées pour la suppression
  • Nettoyer les fichiers temporaires et les caches
  • Optimiser l'utilisation du stockage
  • Programmer la maintenance régulière basée sur les modèles d'utilisation

Dépannage des problèmes courants

1. Erreurs de permissions

# Corriger les problèmes de permissions
sudo chown -R $(whoami) /Users/$(whoami)/Documents
sudo chmod -R 755 /Users/$(whoami)/Documents

2. Métadonnées non disponibles

# Vérifier si l'indexation Spotlight est activée
mdutil -s /
# Re-indexer si nécessaire
sudo mdutil -i on /
sudo mdutil -E /

3. Problèmes d'exécution de script

# Rendre le script exécutable
chmod +x nom_script.sh
# Vérifier la version bash
bash --version
# Utiliser le chemin complet pour les commandes
/usr/bin/mdls au lieu de mdls

4. Problèmes de format de date

# Gérer différents formats de date
date -jf "%Y-%m-%d %H:%M:%S %z" "2024-01-01 12:00:00 +0000" +"%Y-%m-%d %H:%M:%S"

Conclusion

La surveillance de l'utilisation des applications et fichiers est essentielle pour une gestion efficace du parc Mac. Ces scripts fournissent des informations complètes sur le comportement des utilisateurs, les performances du système et la conformité sécuritaire. Une surveillance régulière aide à optimiser les ressources, améliorer l'expérience utilisateur et maintenir les normes de sécurité à travers votre parc Mac.

N'oubliez pas de tester les scripts dans un environnement contrôlé avant de les déployer sur votre parc, et toujours suivre les politiques de sécurité et de confidentialité de votre organisation lors de la surveillance de l'activité des utilisateurs.

Configurer Son d'Alerte et Volume sur macOS

Apprenez à personnaliser les sons d'alerte système et niveaux de volume sur Mac. Essentiel pour créer des expériences audio cohérentes dans les flottes Mac d'entreprise et s'adapter aux différents environnements de travail.

Changer Son d'Alerte

Changez le son d'alerte par défaut de "Tink" vers d'autres sons système disponibles :

#!/bin/bash

# Obtenir le contexte utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configuration
ALERT_SOUND="Submarine"  # Options : Basso, Funk, Glass, Ping, Pop, Submarine, Tink

echo "Définition son d'alerte à : $ALERT_SOUND"

# Appliquer paramètre son d'alerte
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    defaults write .GlobalPreferences com.apple.sound.beep.sound "/System/Library/Sounds/${ALERT_SOUND}.aiff"

echo "✅ Son d'alerte changé vers $ALERT_SOUND"
echo "🔄 Changements prennent effet immédiatement"

Changer Volume d'Alerte

Ajustez le niveau de volume d'alerte (0-100%) :

#!/bin/bash

# Obtenir le contexte utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

# Configuration
ALERT_VOLUME="75"  # Pourcentage volume (0-100)

echo "Définition volume d'alerte à : ${ALERT_VOLUME}%"

# Appliquer paramètre volume d'alerte
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    osascript -e "set volume alert volume $ALERT_VOLUME"

echo "✅ Volume d'alerte défini à ${ALERT_VOLUME}%"

Lister Sons d'Alerte Disponibles

Script pour découvrir tous les sons d'alerte système disponibles :

#!/bin/bash

echo "🔊 Sons d'Alerte Système Disponibles :"
echo "======================================"

# Lister tous fichiers son dans répertoire sons système
SOUNDS_DIR="/System/Library/Sounds"
if [[ -d "$SOUNDS_DIR" ]]; then
    for sound_file in "$SOUNDS_DIR"/*.aiff; do
        if [[ -f "$sound_file" ]]; then
            sound_name=$(basename "$sound_file" .aiff)
            echo "  📢 $sound_name"
        fi
    done
else
    echo "❌ Répertoire sons système non trouvé"
fi

echo ""
echo "💡 Utilisez n'importe lequel de ces noms dans la variable ALERT_SOUND"

Configuration Alerte Complète

Script complet pour configurer son et volume :

#!/bin/bash

# Fonction pour configurer paramètres d'alerte
configure_alert_settings() {
    local sound_name="$1"
    local volume_level="$2"
    
    # Obtenir le contexte utilisateur actuel
    local current_user=$(stat -f "%Su" /dev/console)
    local current_user_uid=$(id -u "$current_user")
    
    echo "=== Configuration Alerte Roundfleet ==="
    echo "👤 Utilisateur : $current_user"
    echo "🔊 Son : $sound_name"
    echo "🔊 Volume : ${volume_level}%"
    echo "====================================="
    
    # Valider que fichier son existe
    local sound_path="/System/Library/Sounds/${sound_name}.aiff"
    if [[ ! -f "$sound_path" ]]; then
        echo "❌ Erreur : Son '$sound_name' non trouvé"
        echo "📋 Sons disponibles :"
        ls /System/Library/Sounds/*.aiff | sed 's|.*/||' | sed 's|\.aiff||' | sed 's/^/  - /'
        return 1
    fi
    
    # Valider plage volume
    if [[ $volume_level -lt 0 || $volume_level -gt 100 ]]; then
        echo "❌ Erreur : Volume doit être entre 0 et 100"
        return 1
    fi
    
    # Appliquer paramètre son d'alerte
    launchctl asuser $current_user_uid sudo -iu "$current_user" \
        defaults write .GlobalPreferences com.apple.sound.beep.sound "$sound_path"
    
    # Appliquer paramètre volume d'alerte
    launchctl asuser $current_user_uid sudo -iu "$current_user" \
        osascript -e "set volume alert volume $volume_level"
    
    echo "✅ Paramètres d'alerte configurés avec succès"
    echo "🎵 Son : $sound_name"
    echo "🔊 Volume : ${volume_level}%"
}

# Configuration entreprise
ALERT_SOUND="Glass"
ALERT_VOLUME="50"

# Appliquer configuration
configure_alert_settings "$ALERT_SOUND" "$ALERT_VOLUME"

Obtenir Paramètres Alerte Actuels

Script pour afficher configuration actuelle son et volume d'alerte :

#!/bin/bash

# Obtenir le contexte utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

echo "📊 Paramètres Alerte Actuels"
echo "============================="

# Obtenir son d'alerte actuel
current_sound=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    defaults read .GlobalPreferences com.apple.sound.beep.sound 2>/dev/null)

if [[ -n "$current_sound" ]]; then
    sound_name=$(basename "$current_sound" .aiff)
    echo "🔊 Son d'Alerte : $sound_name"
else
    echo "🔊 Son d'Alerte : Tink (par défaut)"
fi

# Obtenir volume d'alerte actuel avec AppleScript
current_volume=$(launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    osascript -e "get volume settings" 2>/dev/null | grep -o 'alert volume:[0-9]*' | cut -d: -f2)

if [[ -n "$current_volume" ]]; then
    echo "🔊 Volume d'Alerte : ${current_volume}%"
else
    echo "🔊 Volume d'Alerte : Impossible à déterminer"
fi

echo "👤 Utilisateur : $CURRENT_USER"
echo "🖥️  Appareil : $(hostname)"

Politique Alerte Entreprise

Configuration d'alerte standardisée pour environnements d'entreprise :

#!/bin/bash

# Standardisation alerte entreprise
COMPANY_NAME="Roundfleet"
ENVIRONMENT_TYPE="office"  # Options : office, quiet, presentation, factory

# Définir paramètres spécifiques environnement
case "$ENVIRONMENT_TYPE" in
    "office")
        ALERT_SOUND="Glass"
        ALERT_VOLUME="50"
        ;;
    "quiet")
        ALERT_SOUND="Tink"
        ALERT_VOLUME="25"
        ;;
    "presentation")
        ALERT_SOUND="Pop"
        ALERT_VOLUME="10"
        ;;
    "factory")
        ALERT_SOUND="Basso"
        ALERT_VOLUME="100"
        ;;
    *)
        ALERT_SOUND="Glass"
        ALERT_VOLUME="50"
        ;;
esac

# Fonction pour appliquer politique alerte entreprise
apply_enterprise_alert_policy() {
    local current_user=$(stat -f "%Su" /dev/console)
    local current_user_uid=$(id -u "$current_user")
    
    echo "🏢 Application Politique Alerte Entreprise"
    echo "=========================================="
    echo "Environnement : $ENVIRONMENT_TYPE"
    echo "Appareil : $(hostname)"
    echo "Utilisateur : $current_user"
    echo "Son : $ALERT_SOUND"
    echo "Volume : ${ALERT_VOLUME}%"
    echo "Horodatage : $(date)"
    
    # Appliquer paramètre son
    launchctl asuser $current_user_uid sudo -iu "$current_user" \
        defaults write .GlobalPreferences com.apple.sound.beep.sound "/System/Library/Sounds/${ALERT_SOUND}.aiff"
    
    # Appliquer paramètre volume
    launchctl asuser $current_user_uid sudo -iu "$current_user" \
        osascript -e "set volume alert volume $ALERT_VOLUME"
    
    echo "✅ Politique alerte entreprise appliquée"
    echo "📊 Configuration terminée sur $(hostname)"
}

# Exécuter politique entreprise
apply_enterprise_alert_policy

Réinitialiser aux Paramètres Par Défaut

Restaurer paramètres d'alerte aux valeurs par défaut macOS :

#!/bin/bash

# Obtenir le contexte utilisateur actuel
CURRENT_USER=$(stat -f "%Su" /dev/console)
CURRENT_USER_UID=$(id -u "$CURRENT_USER")

echo "🔄 Réinitialisation paramètres alerte aux valeurs par défaut..."

# Réinitialiser son d'alerte au défaut (Tink)
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    defaults delete .GlobalPreferences com.apple.sound.beep.sound 2>/dev/null || true

# Réinitialiser volume d'alerte au défaut (75%)
launchctl asuser $CURRENT_USER_UID sudo -iu "$CURRENT_USER" \
    osascript -e "set volume alert volume 75"

echo "✅ Paramètres alerte réinitialisés aux valeurs par défaut"
echo "🔊 Son : Tink (par défaut)"
echo "🔊 Volume : 75% (par défaut)"

Utilisation avec Roundfleet

  1. Choisissez son et volume appropriés pour votre environnement
  2. Testez paramètres sur un seul appareil d'abord
  3. Déployez via l'exécution de script distant Roundfleet
  4. Vérifiez paramètres dans la flotte d'appareils

Sons Système Disponibles

Nom SonDescriptionCas d'Usage
BassoProfond, attire l'attentionAlertes haute priorité
FunkModerne, plaisantNotifications générales
GlassClair, netEnvironnements professionnels
PingRapide, subtilDistraction minimale
PopCourt, netConfirmations rapides
SubmarineUnique, distinctifEnvironnements créatifs
TinkSon système par défautConfiguration standard

Directives Environnement

EnvironnementSon RecommandéNiveau Volume
BureauGlass, Tink25-50%
Zones silencieusesPing, Pop10-25%
PrésentationsPop, Tink10%
Usine/BruyantBasso, Funk75-100%
CréatifSubmarine, Funk50-75%

Dépannage

Son ne change pas : Vérifiez que fichier son existe dans /System/Library/Sounds/ Volume ne s'applique pas : Assurez-vous permissions exécution AppleScript Permission refusée : Vérifiez contexte utilisateur avec launchctl asuser

Gestion d'AirDrop sur macOS

Contrôlez la fonctionnalité AirDrop sur vos appareils Roundfleet pour améliorer la sécurité et prévenir les transferts de fichiers non autorisés. Ce tutoriel couvre l'activation, la désactivation, la surveillance et la gestion des paramètres AirDrop pour la conformité d'entreprise et la protection des données.

Comprendre AirDrop sur macOS

AirDrop est la technologie de partage de fichiers sans fil d'Apple qui permet aux utilisateurs de transférer des fichiers entre les appareils Apple proches, notamment :

  • Ordinateurs Mac fonctionnant sous macOS Lion (10.7) ou ultérieur
  • Appareils iOS (iPhone, iPad, iPod touch) avec iOS 7 ou ultérieur
  • Apple Watch pour les types de contenu pris en charge

Considérations de Sécurité

Dans les environnements d'entreprise, AirDrop peut poser des risques de sécurité :

  • Fuite de données par des transferts de fichiers non autorisés
  • Distribution de malware via des fichiers infectés
  • Violations des politiques d'entreprise par un partage incontrôlé
  • Sécurité réseau contournant les contrôles traditionnels de transfert de fichiers

Commandes de Contrôle AirDrop de Base

Désactiver la Fonctionnalité AirDrop

#!/bin/sh

# Désactiver AirDrop en arrêtant l'interface AWDL
sudo ifconfig awdl0 down

echo "Fonctionnalité AirDrop désactivée"

Activer la Fonctionnalité AirDrop

#!/bin/sh

# Activer AirDrop en démarrant l'interface AWDL
sudo ifconfig awdl0 up

echo "Fonctionnalité AirDrop activée"

Vérifier le Statut d'AirDrop

#!/bin/bash

# Vérifier le statut actuel de l'interface AirDrop/AWDL
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 : ACTIVÉ"
        return 0
    elif [[ "$awdl_status" == "inactive" ]]; then
        echo "AirDrop : DÉSACTIVÉ"
        return 1
    else
        echo "AirDrop : STATUT INCONNU"
        return 2
    fi
}

check_airdrop_status

Gestion Avancée d'AirDrop

Script de Contrôle AirDrop Complet

#!/bin/bash

# Gestion avancée d'AirDrop avec validation et journalisation
manage_airdrop() {
    local action="$1"
    local force="${2:-false}"
    
    # Valider les privilèges administrateur
    if [[ $EUID -ne 0 ]]; then
        echo "Erreur : Ce script nécessite des privilèges administrateur"
        echo "Veuillez exécuter avec sudo : sudo $0"
        exit 1
    fi
    
    case "$action" in
        "disable")
            echo "Désactivation de la fonctionnalité AirDrop..."
            
            # Vérifier le statut actuel
            local current_status
            current_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
            
            if [[ "$current_status" == "inactive" ]]; then
                echo "AirDrop est déjà désactivé"
                return 0
            fi
            
            # Désactiver l'interface AWDL
            if ifconfig awdl0 down 2>/dev/null; then
                echo "✓ AirDrop désactivé avec succès"
                
                # Vérifier le changement
                sleep 2
                local new_status
                new_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
                
                if [[ "$new_status" == "inactive" ]]; then
                    echo "✓ Statut AirDrop vérifié : DÉSACTIVÉ"
                    return 0
                else
                    echo "⚠ Attention : Échec de la vérification du statut AirDrop"
                    return 1
                fi
            else
                echo "✗ Échec de la désactivation d'AirDrop"
                return 1
            fi
            ;;
        "enable")
            echo "Activation de la fonctionnalité AirDrop..."
            
            # Vérifier le statut actuel
            local current_status
            current_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
            
            if [[ "$current_status" == "active" ]]; then
                echo "AirDrop est déjà activé"
                return 0
            fi
            
            # Activer l'interface AWDL
            if ifconfig awdl0 up 2>/dev/null; then
                echo "✓ AirDrop activé avec succès"
                
                # Vérifier le changement
                sleep 2
                local new_status
                new_status=$(ifconfig awdl0 2>/dev/null | grep "status:" | awk '{print $2}')
                
                if [[ "$new_status" == "active" ]]; then
                    echo "✓ Statut AirDrop vérifié : ACTIVÉ"
                    return 0
                else
                    echo "⚠ Attention : Échec de la vérification du statut AirDrop"
                    return 1
                fi
            else
                echo "✗ Échec de l'activation d'AirDrop"
                return 1
            fi
            ;;
        "status")
            echo "Vérification du statut d'AirDrop..."
            
            # Obtenir des informations détaillées sur l'interface
            if ifconfig awdl0 &>/dev/null; then
                local status_line
                status_line=$(ifconfig awdl0 | grep "status:")
                echo "Interface AWDL : $status_line"
                
                local flags_line
                flags_line=$(ifconfig awdl0 | head -1 | cut -d'<' -f2 | cut -d'>' -f1)
                echo "Indicateurs d'Interface : $flags_line"
                
                # Vérifier si l'interface est active et en marche
                if echo "$flags_line" | grep -q "UP"; then
                    echo "Statut AirDrop : ACTIVÉ"
                else
                    echo "Statut AirDrop : DÉSACTIVÉ"
                fi
            else
                echo "Interface AWDL : NON DISPONIBLE"
                echo "Statut AirDrop : NON PRIS EN CHARGE"
            fi
            ;;
        *)
            echo "Usage : manage_airdrop [disable|enable|status]"
            echo "  disable - Désactiver la fonctionnalité AirDrop"
            echo "  enable  - Activer la fonctionnalité AirDrop"
            echo "  status  - Vérifier le statut actuel d'AirDrop"
            return 1
            ;;
    esac
}

# Exécuter la fonction avec les arguments fournis
manage_airdrop "$@"

Gestion des Paramètres de Découverte AirDrop au Niveau Utilisateur

#!/bin/bash

# Gérer les paramètres de découverte AirDrop au niveau utilisateur
manage_airdrop_discovery() {
    local username="$1"
    local setting="$2"
    
    # Valider les entrées
    if [[ -z "$username" || -z "$setting" ]]; then
        echo "Usage : manage_airdrop_discovery <username> <off|contacts|everyone>"
        return 1
    fi
    
    # Vérifier si l'utilisateur existe
    if ! id "$username" &>/dev/null; then
        echo "Erreur : L'utilisateur '$username' n'existe pas"
        return 1
    fi
    
    # Mapper le paramètre à une valeur numérique
    local discovery_value
    case "$setting" in
        "off")
            discovery_value="0"
            ;;
        "contacts")
            discovery_value="1"
            ;;
        "everyone")
            discovery_value="2"
            ;;
        *)
            echo "Erreur : Paramètre invalide '$setting'"
            echo "Options valides : off, contacts, everyone"
            return 1
            ;;
    esac
    
    echo "Configuration de la découverte AirDrop à '$setting' pour l'utilisateur : $username"
    
    # Définir la préférence pour l'utilisateur
    if sudo -u "$username" defaults write com.apple.sharingd DiscoverableMode -int "$discovery_value"; then
        echo "✓ Paramètre de découverte AirDrop mis à jour"
        
        # Redémarrer le démon de partage pour appliquer les changements
        sudo -u "$username" killall sharingd 2>/dev/null
        
        echo "✓ Paramètres appliqués avec succès"
        return 0
    else
        echo "✗ Échec de la mise à jour du paramètre de découverte AirDrop"
        return 1
    fi
}

# Exemples d'utilisation
manage_airdrop_discovery "$(whoami)" "contacts"

Gestion des Politiques AirDrop d'Entreprise

#!/bin/bash

# Application des politiques AirDrop d'entreprise
apply_airdrop_policy() {
    local policy_type="$1"
    local apply_to_all_users="${2:-false}"
    
    echo "=== Application de la Politique AirDrop : $policy_type ==="
    
    case "$policy_type" in
        "corporate_lockdown")
            echo "Application de la politique de verrouillage d'entreprise..."
            
            # Désactiver AirDrop à l'échelle du système
            sudo ifconfig awdl0 down
            
            # Désactiver pour tous les utilisateurs
            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 "Désactivation d'AirDrop pour l'utilisateur : $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 0
                done
            fi
            
            echo "✓ Politique de verrouillage d'entreprise appliquée"
            ;;
        "contacts_only")
            echo "Application de la politique contacts uniquement..."
            
            # Activer AirDrop mais restreindre aux 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 "Configuration contacts uniquement pour l'utilisateur : $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 1
                done
            fi
            
            echo "✓ Politique contacts uniquement appliquée"
            ;;
        "unrestricted")
            echo "Application de la politique non restreinte..."
            
            # Activer AirDrop avec découverte complète
            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 "Configuration non restreinte pour l'utilisateur : $user"
                    sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int 2
                done
            fi
            
            echo "✓ Politique non restreinte appliquée"
            ;;
        *)
            echo "Erreur : Type de politique inconnu '$policy_type'"
            echo "Politiques disponibles : corporate_lockdown, contacts_only, unrestricted"
            return 1
            ;;
    esac
}

# Utilisation
apply_airdrop_policy "corporate_lockdown" "true"

Système de Gestion AirDrop d'Entreprise

#!/bin/bash

# Outil de Gestion AirDrop Roundfleet
# Contrôle et surveillance complets d'AirDrop pour les appareils de flotte

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

# Créer les répertoires s'ils n'existent pas
mkdir -p "$REPORT_DIR" "$CONFIG_DIR" "$POLICY_DIR"

# Modèles de politiques AirDrop
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"
)

# Paramètres de conformité de sécurité
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"
)

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

# Surveillance avancée du statut AirDrop
monitor_airdrop_status() {
    local detailed="${1:-false}"
    
    log_action "Surveillance du statut AirDrop (détaillé : $detailed)"
    
    echo "=== Moniteur de Statut AirDrop ==="
    
    # Vérifier le statut de l'interface AWDL
    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 "Statut Interface AWDL : $awdl_status"
    echo "Indicateurs d'Interface : $awdl_flags"
    echo "Adresse IP AWDL : $awdl_ip"
    
    # Vérifier l'activation d'AirDrop à l'échelle du système
    local system_airdrop_enabled="false"
    if [[ "$awdl_status" == "active" ]] && echo "$awdl_flags" | grep -q "UP"; then
        system_airdrop_enabled="true"
    fi
    
    echo "Statut AirDrop Système : $([ "$system_airdrop_enabled" == "true" ] && echo "ACTIVÉ" || echo "DÉSACTIVÉ")"
    
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "=== Analyse Détaillée ==="
        
        # Vérifier les paramètres au niveau utilisateur
        local users
        users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
        
        echo "Paramètres AirDrop au Niveau Utilisateur :"
        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="DÉSACTIVÉ" ;;
                "1") setting_text="CONTACTS UNIQUEMENT" ;;
                "2") setting_text="TOUT LE MONDE" ;;
                *) setting_text="NON DÉFINI" ;;
            esac
            
            echo "  $user : $setting_text"
        done
        
        # Vérifier la connectivité réseau
        echo ""
        echo "Informations Interface Réseau :"
        echo "Statut Wi-Fi : $(networksetup -getairportpower en0 | awk '{print $4}')"
        echo "Statut Bluetooth : $(system_profiler SPBluetoothDataType | grep "State:" | awk '{print $2}' | head -1)"
        
        # Vérifier les processus en cours d'exécution
        echo ""
        echo "Processus Connexes :"
        ps aux | grep -E "(sharingd|airportd)" | grep -v grep | awk '{print $11}'
    fi
}

# Application complète des politiques AirDrop
enforce_airdrop_policy() {
    local policy_name="$1"
    local target_users="$2"
    local dry_run="${3:-false}"
    
    log_action "Application de la politique AirDrop : $policy_name (dry_run : $dry_run)"
    
    if [[ -z "${AIRDROP_POLICIES[$policy_name]}" ]]; then
        log_action "ERREUR : Politique inconnue '$policy_name'"
        echo "Politiques disponibles : ${!AIRDROP_POLICIES[*]}"
        return 1
    fi
    
    # Analyser la configuration de politique
    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 "=== Application de la Politique : $policy_name ==="
    echo "État AirDrop : $airdrop_state"
    echo "Paramètre de Découverte : $discovery_setting"
    echo "Niveau de Surveillance : $monitoring_level"
    echo "Niveau de Journalisation : $logging_level"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "MODE TEST - Aucun changement ne sera appliqué"
        return 0
    fi
    
    # Appliquer les paramètres au niveau système
    case "$airdrop_state" in
        "enabled")
            echo "Activation d'AirDrop à l'échelle du système..."
            sudo ifconfig awdl0 up
            ;;
        "disabled")
            echo "Désactivation d'AirDrop à l'échelle du système..."
            sudo ifconfig awdl0 down
            ;;
    esac
    
    # Appliquer les paramètres au niveau utilisateur
    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 "Application des paramètres pour l'utilisateur : $user"
            sudo -u "$user" defaults write com.apple.sharingd DiscoverableMode -int "$discovery_value"
            
            # Redémarrer le démon de partage
            sudo -u "$user" killall sharingd 2>/dev/null
        fi
    done
    
    # Configurer la surveillance
    configure_airdrop_monitoring "$monitoring_level" "$logging_level"
    
    # Générer un rapport de conformité de politique
    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 "Application de politique terminée : $report_file"
    echo "$report_file"
}

# Configurer la surveillance et la journalisation AirDrop
configure_airdrop_monitoring() {
    local monitoring_level="$1"
    local logging_level="$2"
    
    echo "Configuration de la surveillance (niveau : $monitoring_level, journalisation : $logging_level)"
    
    case "$monitoring_level" in
        "monitoring_enabled")
            # Créer un script de surveillance
            cat > "/usr/local/bin/roundfleet_airdrop_monitor.sh" << 'EOF'
#!/bin/bash
# Moniteur d'activité AirDrop
while true; do
    # Surveiller les changements d'interface AWDL
    ifconfig awdl0 | grep "status:" >> /var/log/roundfleet_airdrop_activity.log
    sleep 30
done
EOF
            chmod +x "/usr/local/bin/roundfleet_airdrop_monitor.sh"
            
            # Créer LaunchDaemon pour la surveillance
            cat > "/Library/LaunchDaemons/com.roundfleet.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.roundfleet.airdrop.monitor</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/roundfleet_airdrop_monitor.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
EOF
            launchctl load "/Library/LaunchDaemons/com.roundfleet.airdrop.monitor.plist"
            ;;
        "monitoring_disabled")
            # Supprimer les composants de surveillance
            launchctl unload "/Library/LaunchDaemons/com.roundfleet.airdrop.monitor.plist" 2>/dev/null
            rm -f "/Library/LaunchDaemons/com.roundfleet.airdrop.monitor.plist"
            rm -f "/usr/local/bin/roundfleet_airdrop_monitor.sh"
            ;;
    esac
}

# Générer un rapport complet de conformité de politique
generate_policy_report() {
    local policy_name="$1"
    local report_file="$2"
    
    # Obtenir l'état actuel du système
    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"
    
    # Obtenir les paramètres utilisateur
    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
    
    # Ajouter les paramètres spécifiques aux utilisateurs
    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 "DÉSACTIVÉ" elif $setting == 1 then "CONTACTS_UNIQUEMENT" elif $setting == 2 then "TOUT_LE_MONDE" else "NON_DÉFINI" end)
           }]' "$report_file" > "${report_file}.tmp" && mv "${report_file}.tmp" "$report_file"
    done
    
    log_action "Rapport de politique généré : $report_file"
}

# Audit AirDrop à l'échelle de la flotte
audit_fleet_airdrop() {
    local scope="${1:-all}"
    
    echo "=== Audit AirDrop de Flotte ==="
    log_action "Début de l'audit AirDrop de flotte (portée : $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
    
    # Analyse au niveau système
    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"
    
    # Analyse au niveau utilisateur
    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
        
        # Vérifier les préoccupations de sécurité
        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
    
    # Générer un résumé de sécurité
    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 terminé. $security_issues problèmes de sécurité trouvés."
    log_action "Audit de flotte terminé : $audit_report"
    echo "$audit_report"
}

# Fonction d'exécution principale
main() {
    local action="${1:-status}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    
    log_action "=== Gestion AirDrop Roundfleet Démarrée ==="
    log_action "Action : $action"
    
    # Assurer les privilèges requis pour la plupart des opérations
    if [[ "$action" != "status" && "$action" != "help" && $EUID -ne 0 ]]; then
        echo "Erreur : Cette action nécessite des privilèges administrateur"
        echo "Veuillez exécuter avec sudo : sudo $0 $*"
        exit 1
    fi
    
    case "$action" in
        "disable")
            echo "Désactivation d'AirDrop..."
            sudo ifconfig awdl0 down && echo "✓ AirDrop désactivé" || echo "✗ Échec de la désactivation d'AirDrop"
            ;;
        "enable")
            echo "Activation d'AirDrop..."
            sudo ifconfig awdl0 up && echo "✓ AirDrop activé" || echo "✗ Échec de l'activation d'AirDrop"
            ;;
        "status")
            monitor_airdrop_status "$param1"
            ;;
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Politiques disponibles : ${!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 - Désactiver AirDrop à l'échelle du système"
            echo "  enable - Activer AirDrop à l'échelle du système"
            echo "  status [detailed] - Vérifier le statut d'AirDrop"
            echo "  policy <policy_name> [users] [dry_run] - Appliquer une politique"
            echo "  user <username> <setting> - Définir le paramètre AirDrop utilisateur"
            echo "  audit [scope] - Auditer la sécurité AirDrop"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Politiques : ${!AIRDROP_POLICIES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion AirDrop terminée ==="
}

# Exécuter la fonction principale
main "$@"

Meilleures Pratiques de Sécurité AirDrop

Politiques de Sécurité d'Entreprise

#!/bin/bash

# Implémenter les politiques de sécurité AirDrop d'entreprise
implement_corporate_security() {
    echo "=== Implémentation de la Sécurité AirDrop d'Entreprise ==="
    
    # 1. Désactiver AirDrop sur les ordinateurs partagés/publics
    echo "Désactivation d'AirDrop sur les postes de travail partagés..."
    sudo ifconfig awdl0 down
    
    # 2. Définir des paramètres par défaut restrictifs pour les utilisateurs
    echo "Configuration des paramètres par défaut restrictifs pour AirDrop..."
    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. Créer une application de politique à l'échelle du système
    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. Définir les permissions appropriées
    chmod 644 "/Library/Preferences/com.apple.sharingd.plist"
    chown root:wheel "/Library/Preferences/com.apple.sharingd.plist"
    
    echo "✓ Politiques de sécurité d'entreprise implémentées"
}

implement_corporate_security

Surveillance de Conformité

#!/bin/bash

# Surveiller la conformité AirDrop avec les politiques de sécurité
monitor_compliance() {
    local compliance_standard="$1"
    
    echo "=== Surveillance de Conformité AirDrop : $compliance_standard ==="
    
    case "$compliance_standard" in
        "hipaa")
            # Conformité santé - AirDrop doit être désactivé
            if ifconfig awdl0 | grep -q "status: active"; then
                echo "⚠ VIOLATION HIPAA : AirDrop est activé"
                echo "Recommandation : Désactiver AirDrop pour prévenir les fuites de PHI"
                return 1
            else
                echo "✓ CONFORME HIPAA : AirDrop est désactivé"
            fi
            ;;
        "pci_dss")
            # Conformité industrie des cartes de paiement
            if ifconfig awdl0 | grep -q "status: active"; then
                echo "⚠ VIOLATION PCI DSS : AirDrop crée un chemin réseau incontrôlé"
                echo "Recommandation : Désactiver AirDrop dans l'environnement de données des porteurs de cartes"
                return 1
            else
                echo "✓ CONFORME PCI DSS : AirDrop est désactivé"
            fi
            ;;
        "sox")
            # Conformité Sarbanes-Oxley pour les données financières
            echo "Vérification de la conformité SOX pour la protection des données financières..."
            # Implémentation spécifique au traitement des données financières
            ;;
        *)
            echo "Standard de conformité inconnu : $compliance_standard"
            return 1
            ;;
    esac
}

# Utilisation
monitor_compliance "hipaa"

Dépannage des Problèmes AirDrop

Diagnostics Réseau

#!/bin/bash

# Dépannage complet d'AirDrop
troubleshoot_airdrop() {
    echo "=== Diagnostics de Dépannage AirDrop ==="
    
    echo "1. Vérification de l'Interface AWDL..."
    if ifconfig awdl0 &>/dev/null; then
        ifconfig awdl0 | head -10
    else
        echo "Interface AWDL non disponible"
    fi
    
    echo -e "\n2. Vérification du Statut Wi-Fi..."
    networksetup -getairportpower en0
    
    echo -e "\n3. Vérification du Statut Bluetooth..."
    system_profiler SPBluetoothDataType | grep -A 5 "State:"
    
    echo -e "\n4. Vérification des Paramètres du Pare-feu..."
    /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
    
    echo -e "\n5. Vérification des Préférences de Partage..."
    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 "non défini")
        echo "Utilisateur $user : $setting"
    done
    
    echo -e "\n6. Vérification des Processus Connexes..."
    ps aux | grep -E "(sharingd|airportd|bluetoothd)" | grep -v grep
    
    echo -e "\n7. Résumé des Interfaces Réseau..."
    networksetup -listallhardwareports | grep -A 1 "Wi-Fi\|Bluetooth"
}

troubleshoot_airdrop

Réinitialiser la Configuration AirDrop

#!/bin/bash

# Réinitialiser AirDrop à la configuration par défaut
reset_airdrop_config() {
    echo "=== Réinitialisation de la Configuration AirDrop ==="
    
    # Arrêter le démon de partage
    echo "Arrêt du démon de partage..."
    sudo killall sharingd 2>/dev/null
    
    # Réinitialiser l'interface AWDL
    echo "Réinitialisation de l'interface AWDL..."
    sudo ifconfig awdl0 down
    sleep 2
    sudo ifconfig awdl0 up
    
    # Effacer les préférences utilisateur
    echo "Effacement des préférences AirDrop utilisateur..."
    local users
    users=$(dscl . -list /Users | grep -v "^_" | grep -v "daemon\|nobody\|root")
    
    for user in $users; do
        echo "Réinitialisation des préférences pour l'utilisateur : $user"
        sudo -u "$user" defaults delete com.apple.sharingd DiscoverableMode 2>/dev/null || true
    done
    
    # Supprimer les politiques à l'échelle du système
    echo "Suppression des politiques AirDrop à l'échelle du système..."
    sudo rm -f "/Library/Preferences/com.apple.sharingd.plist"
    
    # Redémarrer le démon de partage
    echo "Redémarrage du démon de partage..."
    sudo launchctl kickstart -k system/com.apple.sharingd
    
    echo "✓ Configuration AirDrop réinitialisée aux paramètres par défaut"
}

reset_airdrop_config

Notes Importantes

  • Interface AWDL - Apple Wireless Direct Link est la technologie sous-jacente d'AirDrop
  • Privilèges administrateur requis pour le contrôle AirDrop à l'échelle du système
  • Paramètres au niveau utilisateur peuvent remplacer les politiques système sauf si appliquées
  • Dépendances réseau - Nécessite que le Wi-Fi et le Bluetooth soient activés
  • Implications de sécurité - Considérer les politiques d'entreprise avant l'activation
  • Exigences de conformité - Certaines industries nécessitent la désactivation d'AirDrop
  • Tester minutieusement - Valider les changements sur les appareils de test avant le déploiement en flotte

Gestion des Droits Administrateur d'Entreprise sur macOS

Gérez et contrôlez les privilèges administrateur sur vos appareils Roundfleet en utilisant des outils de ligne de commande avancés et des politiques de gestion de privilèges centralisées. Ce tutoriel couvre les droits admin temporaires, le contrôle d'escalade de privilèges, la gouvernance de sécurité et la gestion de droits administrateur de niveau entreprise avec des capacités complètes d'audit et de conformité.

Comprendre la Gestion des Droits Admin macOS

macOS fournit plusieurs outils et méthodes pour gérer les privilèges administrateur :

  • dscl - Utilitaire en ligne de commande des Services d'Annuaire pour la gestion des utilisateurs et groupes
  • sudo - Exécuter des commandes avec des privilèges élevés
  • launchctl - Gestion des daemons de lancement pour les tâches programmées
  • Framework des Groupes - Gestion intégrée de l'appartenance au groupe admin
  • Framework de Sécurité - Autorisation et validation des privilèges

La gestion d'entreprise des droits admin nécessite un équilibre délicat entre sécurité, productivité et exigences de conformité.

Commandes de Base des Droits Admin

Accorder des Droits Admin (Base)

#!/bin/bash

# Octroi de base des droits admin
grant_admin_rights_basic() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage : grant_admin_rights_basic <nom_utilisateur>"
        return 1
    fi
    
    # Vérifier que l'utilisateur existe
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ Utilisateur '$username' non trouvé"
        return 1
    fi
    
    # Ajouter l'utilisateur au groupe admin
    dscl . -append /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Droits admin accordés à l'utilisateur : $username"
        return 0
    else
        echo "❌ Échec de l'octroi des droits admin à l'utilisateur : $username"
        return 1
    fi
}

# Exemple d'utilisation
# grant_admin_rights_basic "jean.dupont"

Révoquer les Droits Admin (Base)

#!/bin/bash

# Révocation de base des droits admin
revoke_admin_rights_basic() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage : revoke_admin_rights_basic <nom_utilisateur>"
        return 1
    fi
    
    # Vérifier que l'utilisateur existe
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ Utilisateur '$username' non trouvé"
        return 1
    fi
    
    # Supprimer l'utilisateur du groupe admin
    dscl . -delete /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Droits admin révoqués de l'utilisateur : $username"
        return 0
    else
        echo "❌ Échec de la révocation des droits admin de l'utilisateur : $username"
        return 1
    fi
}

# Exemple d'utilisation
# revoke_admin_rights_basic "jean.dupont"

Vérifier le Statut Admin

#!/bin/bash

# Vérifier si l'utilisateur a des privilèges admin
check_admin_status() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage : check_admin_status <nom_utilisateur>"
        return 1
    fi
    
    # Vérifier si l'utilisateur est dans le groupe admin
    local admin_members
    admin_members=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | grep -o "$username")
    
    if [[ -n "$admin_members" ]]; then
        echo "✅ L'utilisateur '$username' a des privilèges admin"
        return 0
    else
        echo "❌ L'utilisateur '$username' n'a pas de privilèges admin"
        return 1
    fi
}

# Lister tous les utilisateurs admin
list_admin_users() {
    echo "=== Utilisateurs Admin Actuels ==="
    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 "Comptes administrateur :"
        while IFS= read -r user; do
            # Obtenir le nom réel de l'utilisateur si disponible
            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 "Aucun utilisateur admin trouvé"
    fi
    echo ""
}

# Exemple d'utilisation
# check_admin_status "jean.dupont"
# list_admin_users

Gestion Avancée des Droits Admin

Droits Admin Temporaires

#!/bin/bash

# Droits admin temporaires améliorés
grant_temporary_admin_rights() {
    local username="$1"
    local duration_minutes="${2:-30}"
    local reason="${3:-Tâche administrative}"
    local require_confirmation="${4:-true}"
    
    if [[ -z "$username" ]]; then
        echo "Usage : grant_temporary_admin_rights <nom_utilisateur> [durée_minutes] [raison] [confirmation_requise]"
        return 1
    fi
    
    # Vérifier que l'utilisateur existe
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        echo "❌ Utilisateur '$username' non trouvé"
        return 1
    fi
    
    # Vérifier si l'utilisateur a déjà des droits admin
    if check_admin_status "$username" >/dev/null; then
        echo "⚠️  L'utilisateur '$username' a déjà des privilèges admin"
        read -p "Continuer avec la configuration admin temporaire ? (o/N) : " -n 1 -r
        echo
        if [[ ! $REPLY =~ ^[OoYy]$ ]]; then
            return 1
        fi
    fi
    
    # Afficher la boîte de dialogue de confirmation si requise
    if [[ "$require_confirmation" == "true" ]]; then
        osascript -e "display dialog \"Vous avez reçu des droits administrateur pour $duration_minutes minutes.\\n\\nRaison : $reason\\n\\nVeuillez ne pas abuser de ce privilège.\" buttons {\"Accepter les Droits Admin\"} default button 1 with title \"Octroi de Droits Admin Roundfleet\""
        
        if [[ $? -ne 0 ]]; then
            echo "❌ L'utilisateur a refusé l'octroi des droits admin"
            return 1
        fi
    fi
    
    # Créer le répertoire de suivi
    local tracking_dir="/private/var/roundfleet_admin_tracking"
    sudo mkdir -p "$tracking_dir"
    
    # Créer le fichier de suivi utilisateur avec métadonnées
    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
    
    # Accorder les droits admin
    dscl . -append /Groups/admin GroupMembership "$username"
    
    if [[ $? -eq 0 ]]; then
        echo "✅ Droits admin temporaires accordés à '$username' pour $duration_minutes minutes"
        
        # Créer le script de suppression
        create_admin_removal_script "$username" "$duration_minutes"
        
        # Programmer la suppression
        schedule_admin_removal "$username" "$duration_minutes"
        
        return 0
    else
        echo "❌ Échec de l'octroi des droits admin à '$username'"
        rm -f "$tracking_file"
        return 1
    fi
}

# Créer le script de suppression admin
create_admin_removal_script() {
    local username="$1"
    local duration_minutes="$2"
    
    local script_path="/Library/Application Support/Roundfleet/remove_admin_${username}.sh"
    mkdir -p "$(dirname "$script_path")"
    
    cat > "$script_path" <<'EOF'
#!/bin/bash

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

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

log_action "Début de suppression des droits admin pour l'utilisateur : $USERNAME"

# Vérifier si l'utilisateur a encore des droits admin
if dscl . -read /Groups/admin GroupMembership 2>/dev/null | grep -q "$USERNAME"; then
    # Supprimer les droits admin
    dscl . -delete /Groups/admin GroupMembership "$USERNAME"
    
    if [[ $? -eq 0 ]]; then
        log_action "✅ Droits admin supprimés avec succès de l'utilisateur : $USERNAME"
        
        # Notifier l'utilisateur s'il est connecté
        if pgrep -u "$USERNAME" >/dev/null; then
            sudo -u "$USERNAME" osascript -e 'display notification "Vos privilèges administrateur temporaires ont expiré." with title "Droits Admin Roundfleet"' 2>/dev/null
        fi
    else
        log_action "❌ Échec de suppression des droits admin de l'utilisateur : $USERNAME"
    fi
else
    log_action "⚠️  L'utilisateur $USERNAME n'avait pas de droits admin (déjà supprimés ou jamais accordés)"
fi

# Nettoyer le fichier de suivi
if [[ -f "$TRACKING_FILE" ]]; then
    # Archiver les données de suivi
    ARCHIVE_DIR="/var/log/roundfleet_admin_archive"
    mkdir -p "$ARCHIVE_DIR"
    mv "$TRACKING_FILE" "$ARCHIVE_DIR/${USERNAME}_admin_$(date +%Y%m%d_%H%M%S).json"
    log_action "Données de suivi des droits admin archivées pour l'utilisateur : $USERNAME"
fi

# Supprimer le daemon de lancement
PLIST_PATH="/Library/LaunchDaemons/com.roundfleet.remove_admin_${USERNAME}.plist"
if [[ -f "$PLIST_PATH" ]]; then
    launchctl unload "$PLIST_PATH" 2>/dev/null
    rm -f "$PLIST_PATH"
    log_action "Daemon de lancement supprimé pour l'utilisateur : $USERNAME"
fi

# Supprimer ce script
rm -f "$0"

log_action "Processus de suppression des droits admin terminé pour l'utilisateur : $USERNAME"
exit 0
EOF
    
    # Remplacer le placeholder par le nom d'utilisateur réel
    sed -i '' "s/{{USERNAME}}/$username/g" "$script_path"
    
    # Définir les permissions
    chmod 755 "$script_path"
    chown root:wheel "$script_path"
}

# Programmer la suppression admin avec launchd
schedule_admin_removal() {
    local username="$1"
    local duration_minutes="$2"
    
    local plist_path="/Library/LaunchDaemons/com.roundfleet.remove_admin_${username}.plist"
    local script_path="/Library/Application Support/Roundfleet/remove_admin_${username}.sh"
    
    # Calculer l'heure d'exécution
    local start_time
    start_time=$(date -u -v+${duration_minutes}M +%Y-%m-%dT%H:%M:%SZ)
    
    # Créer le plist du daemon de lancement
    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.roundfleet.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
    
    # Définir les permissions
    chown root:wheel "$plist_path"
    chmod 644 "$plist_path"
    
    # Charger le daemon
    launchctl load "$plist_path"
    
    echo "⏰ Suppression des droits admin programmée pour $start_time"
}

# Exemple d'utilisation
# grant_temporary_admin_rights "jean.dupont" 30 "Installation logiciel" true

Système de Gestion des Droits Admin d'Entreprise

#!/bin/bash

# Système de Gestion des Droits Admin d'Entreprise Roundfleet
# Gestion complète des privilèges, gouvernance de sécurité et surveillance de conformité

# Configuration
LOG_FILE="/var/log/roundfleet_admin_rights.log"
CONFIG_FILE="/etc/roundfleet/admin_rights_config.conf"
AUDIT_DIR="/var/log/roundfleet_admin_audit"
POLICY_DIR="/etc/roundfleet/admin_policies"
TRACKING_DIR="/private/var/roundfleet_admin_tracking"

# Créer la structure de répertoires
setup_directories() {
    mkdir -p "$(dirname "$LOG_FILE")" "$AUDIT_DIR" "$POLICY_DIR" "$TRACKING_DIR" "$(dirname "$CONFIG_FILE")"
    touch "$LOG_FILE"
    
    # Définir les permissions appropriées
    chmod 755 "$AUDIT_DIR" "$POLICY_DIR"
    chmod 700 "$TRACKING_DIR"  # Restreindre l'accès aux données de suivi
}

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

# Charger la configuration
load_config() {
    if [[ -f "$CONFIG_FILE" ]]; then
        source "$CONFIG_FILE"
    else
        # Définir les valeurs par défaut
        MAX_ADMIN_DURATION="${MAX_ADMIN_DURATION:-480}"  # 8 heures max
        DEFAULT_ADMIN_DURATION="${DEFAULT_ADMIN_DURATION:-30}"  # 30 minutes par défaut
        REQUIRE_JUSTIFICATION="${REQUIRE_JUSTIFICATION:-true}"
        ENABLE_NOTIFICATIONS="${ENABLE_NOTIFICATIONS:-true}"
        AUDIT_ALL_CHANGES="${AUDIT_ALL_CHANGES:-true}"
        PROTECTED_ACCOUNTS="${PROTECTED_ACCOUNTS:-root,admin,roundfleet}"
    fi
}

# Octroi de droits admin d'entreprise avec application de politique
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 "ERREUR : Nom d'utilisateur requis pour l'octroi de droits admin"
        return 1
    fi
    
    # Définir la durée par défaut si non fournie
    if [[ -z "$duration_minutes" ]]; then
        duration_minutes="$DEFAULT_ADMIN_DURATION"
    fi
    
    # Valider la durée par rapport à la politique
    if [[ "$duration_minutes" -gt "$MAX_ADMIN_DURATION" ]]; then
        log_action "ERREUR : Durée demandée ($duration_minutes min) dépasse le maximum autorisé ($MAX_ADMIN_DURATION min)"
        return 1
    fi
    
    # Exiger une justification si la politique est activée
    if [[ "$REQUIRE_JUSTIFICATION" == "true" && -z "$reason" ]]; then
        log_action "ERREUR : Justification requise pour l'octroi de droits admin"
        return 1
    fi
    
    # Vérifier que l'utilisateur existe
    if ! dscl . -read /Users/"$username" >/dev/null 2>&1; then
        log_action "ERREUR : Utilisateur '$username' non trouvé"
        return 1
    fi
    
    # Vérifier les comptes protégés
    if echo "$PROTECTED_ACCOUNTS" | grep -q "$username"; then
        log_action "ERREUR : Impossible de modifier les droits admin pour le compte protégé : $username"
        return 1
    fi
    
    # Vérifier les droits admin existants
    local current_admin_status
    if check_admin_status "$username" >/dev/null; then
        current_admin_status="already_admin"
    else
        current_admin_status="standard_user"
    fi
    
    # Créer une entrée d'audit
    local audit_id
    audit_id=$(create_audit_entry "grant" "$username" "$duration_minutes" "$reason" "$approved_by" "$current_admin_status")
    
    # Accorder les droits admin
    if [[ "$current_admin_status" == "standard_user" ]]; then
        dscl . -append /Groups/admin GroupMembership "$username"
        
        if [[ $? -ne 0 ]]; then
            log_action "ERREUR : Échec de l'octroi des droits admin à '$username'"
            update_audit_entry "$audit_id" "failed" "Échec de modification du groupe admin"
            return 1
        fi
    fi
    
    # Créer une entrée de suivi
    create_tracking_entry "$username" "$duration_minutes" "$reason" "$approved_by" "$audit_id"
    
    # Programmer la suppression si temporaire
    if [[ "$duration_minutes" -gt 0 ]]; then
        schedule_enterprise_admin_removal "$username" "$duration_minutes" "$audit_id"
    fi
    
    # Envoyer des notifications
    if [[ "$ENABLE_NOTIFICATIONS" == "true" ]]; then
        send_admin_notification "$username" "granted" "$duration_minutes" "$reason"
    fi
    
    log_action "✅ Droits admin accordés à '$username' pour $duration_minutes minutes (ID Audit : $audit_id)"
    update_audit_entry "$audit_id" "success" "Droits admin accordés avec succès"
    
    return 0
}

# Fonction de gestion principale
main() {
    local action="${1:-status}"
    local parameter1="$2"
    local parameter2="$3"
    local parameter3="$4"
    local parameter4="$5"
    
    setup_directories
    log_action "Gestion des Droits Admin Roundfleet démarrée avec l'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
            ;;
        "status"|*)
            list_admin_users
            ;;
    esac
    
    log_action "Gestion des Droits Admin Roundfleet terminée avec l'action : $action"
}

# Exécuter la fonction principale avec tous les arguments
main "$@"

Modèles de Politiques de Droits Admin

Politique de Droits Admin d'Entreprise

# /etc/roundfleet/admin_rights_config.conf
# Configuration des Droits Admin d'Entreprise Roundfleet

# Limites de durée (en minutes)
MAX_ADMIN_DURATION="480"        # 8 heures maximum
DEFAULT_ADMIN_DURATION="30"     # 30 minutes par défaut
WARNING_BEFORE_EXPIRY="5"       # Avertissement 5 minutes avant

# Exigences de sécurité
REQUIRE_JUSTIFICATION="true"
REQUIRE_APPROVAL="true"
MINIMUM_JUSTIFICATION_LENGTH="10"

# Paramètres de notification
ENABLE_NOTIFICATIONS="true"
NOTIFY_SECURITY_TEAM="true"
SECURITY_TEAM_EMAIL="[email protected]"

# Paramètres d'audit
AUDIT_ALL_CHANGES="true"
RETAIN_AUDIT_LOGS="90"          # 90 jours
ENABLE_REALTIME_MONITORING="true"

# Comptes protégés (ne peuvent pas être modifiés)
PROTECTED_ACCOUNTS="root,admin,roundfleet,securite"

# Flux d'approbation
REQUIRE_MANAGER_APPROVAL="true"
ENABLE_EMERGENCY_BYPASS="false"
EMERGENCY_BYPASS_ACCOUNTS="securite,ciso"

Politique Environnement Haute Sécurité

# /etc/roundfleet/admin_policies/high_security.policy
# Politique de Droits Admin Haute Sécurité Roundfleet

# Limites de durée strictes
MAX_ADMIN_DURATION="60"         # 1 heure maximum
DEFAULT_ADMIN_DURATION="15"     # 15 minutes par défaut
AUTO_REVOKE_IDLE="true"         # Révoquer si utilisateur inactif
IDLE_TIMEOUT_MINUTES="10"       # 10 minutes timeout inactivité

# Sécurité renforcée
REQUIRE_JUSTIFICATION="true"
REQUIRE_TWO_PERSON_APPROVAL="true"
ENABLE_SESSION_RECORDING="true"
BLOCK_ADMIN_OUTSIDE_HOURS="true"
ALLOWED_HOURS="09-17"           # 9h à 17h
ALLOWED_DAYS="1-5"              # Lundi au vendredi

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

Fonctions de Sécurité et Conformité

Vérification de Conformité des Droits Admin

#!/bin/bash

# Vérification complète de conformité des droits admin
check_admin_compliance() {
    echo "🔍 Vérification de Conformité des Droits Admin"
    echo "============================================="
    echo ""
    
    local compliance_issues=()
    local compliance_warnings=()
    
    # Vérifier les comptes admin permanents non autorisés
    echo "1. COMPTES ADMIN PERMANENTS NON AUTORISÉS :"
    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"
            
            # Ignorer les comptes protégés
            if echo "$PROTECTED_ACCOUNTS" | grep -q "$user"; then
                echo "  ✅ $user (Compte protégé)"
                continue
            fi
            
            # Vérifier si l'utilisateur a un suivi admin temporaire
            if [[ ! -f "$tracking_file" ]]; then
                # Pas de suivi = admin permanent (violation potentielle)
                compliance_issues+=("Compte admin permanent sans suivi : $user")
                echo "  ❌ $user (Aucun suivi admin temporaire trouvé)"
            else
                # Vérifier si l'admin temporaire a expiré
                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+=("Admin temporaire expiré toujours actif : $user")
                    echo "  ⚠️  $user (Admin temporaire expiré mais toujours actif)"
                else
                    local reason
                    reason=$(jq -r '.reason' "$tracking_file" 2>/dev/null)
                    echo "  ✅ $user (Admin temporaire, expire : $expires_at, raison : $reason)"
                fi
            fi
        fi
    done <<< "$admin_users"
    echo ""
    
    # Générer le résumé de conformité
    echo "2. RÉSUMÉ DE CONFORMITÉ :"
    echo "------------------------"
    
    if [[ ${#compliance_issues[@]} -eq 0 ]]; then
        echo "  ✅ Aucun problème critique de conformité trouvé"
    else
        echo "  ❌ Problèmes critiques de conformité trouvés :"
        for issue in "${compliance_issues[@]}"; do
            echo "    - $issue"
        done
    fi
    
    if [[ ${#compliance_warnings[@]} -gt 0 ]]; then
        echo "  ⚠️  Avertissements :"
        for warning in "${compliance_warnings[@]}"; do
            echo "    - $warning"
        done
    fi
    
    echo ""
    echo "Recommandations :"
    echo "• Examiner et corriger tout compte admin permanent non autorisé"
    echo "• Implémenter des vérifications de conformité régulières (quotidiennes/hebdomadaires)"
    echo "• Activer la surveillance en temps réel des changements de droits admin"
    echo "• Établir des politiques claires de gouvernance des droits admin"
    echo "• Audit régulier des activités et justifications admin"
    
    # Retourner le code de sortie approprié
    if [[ ${#compliance_issues[@]} -gt 0 ]]; then
        return 1
    else
        return 0
    fi
}

check_admin_compliance

Notes Techniques Importantes

Référence des Commandes DSCL

  • dscl . -append /Groups/admin GroupMembership <user> : Ajouter utilisateur au groupe admin
  • dscl . -delete /Groups/admin GroupMembership <user> : Supprimer utilisateur du groupe admin
  • dscl . -read /Groups/admin GroupMembership : Lister tous les membres du groupe admin
  • dscl . -read /Users/<user> : Obtenir des informations détaillées sur l'utilisateur

Considérations de Sécurité

  1. Principe du Moindre Privilège : Accorder les privilèges minimum nécessaires pour le temps minimum
  2. Piste d'Audit : Maintenir des journaux complets de tous les changements de droits admin
  3. Flux d'Approbation : Implémenter des processus d'approbation pour les octrois de droits admin
  4. Limites de Temps : Toujours utiliser des droits admin temporaires avec expiration automatique
  5. Surveillance : Surveillance en temps réel des activités admin et comportements suspects

Exigences de Conformité

  1. Documentation : Maintenir des enregistrements détaillés des octrois et révocations de droits admin
  2. Justification : Exiger une justification métier pour toutes les escalades de privilèges
  3. Audits Réguliers : Effectuer des vérifications et examens de conformité réguliers
  4. Comptes Protégés : Protéger les comptes système critiques contre les modifications
  5. Politiques de Rétention : Implémenter des politiques appropriées de rétention et archivage des journaux

Cas d'Usage d'Entreprise

  1. Installation de Logiciels : Droits admin temporaires pour les installations d'applications
  2. Maintenance Système : Accès admin programmé pour les fenêtres de maintenance
  3. Réponse d'Urgence : Escalade rapide de privilèges pour la réponse aux incidents
  4. Audit de Conformité : Examens réguliers des droits et activités admin
  5. Sécurité Zero Trust : Vérification continue et accès à privilège minimal

N'oubliez pas de tester tous les scripts sur des appareils individuels avant de les déployer sur votre environnement Roundfleet, et d'assurer la conformité avec les politiques de sécurité d'entreprise et les exigences réglementaires lors de l'implémentation de systèmes de gestion de droits admin d'entreprise.

Configuration d'un Runner GitHub Actions sur Mac Mini (Apple Silicon)

GitHub Actions runner

GitHub Actions est une plateforme CI/CD puissante qui vous permet d'automatiser vos workflows de développement logiciel. Bien que GitHub propose des runners hébergés, les runners auto-hébergés offrent un contrôle et une personnalisation accrus pour votre configuration CI/CD. Ce tutoriel vous guide dans la configuration, la mise en place et la connexion d'un runner auto-hébergé sur un Mac Mini pour exécuter des pipelines macOS.

Prérequis

Avant de commencer, assurez-vous d'avoir :

  • Un Mac Mini (inscrivez-vous sur Roundfleet)
  • Un dépôt GitHub avec des droits d'administrateur
  • Un gestionnaire de paquets installé (de préférence Homebrew)
  • Git installé sur votre système

Étape 1 : Créer un compte utilisateur dédié

D'abord, créez un compte utilisateur dédié pour le runner GitHub Actions :

# Créer le compte utilisateur 'gh-runner'
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

# Définir le mot de passe pour l'utilisateur
sudo dscl . -passwd /Users/gh-runner votre_mot_de_passe

# Ajouter 'gh-runner' au groupe 'admin'
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Basculez vers le nouveau compte utilisateur :

su gh-runner

Étape 2 : Installer les logiciels requis

Installez Git et Rosetta 2 (si vous utilisez Apple Silicon) :

# Installer Git s'il n'est pas déjà installé
brew install git

# Installer Rosetta 2 pour les Mac Apple Silicon
softwareupdate --install-rosetta

Étape 3 : Configurer le Runner GitHub Actions

  1. Allez sur votre dépôt GitHub
  2. Naviguez vers Settings > Actions > Runners

GitHub Actions runner

  1. Cliquez sur "New self-hosted runner" (https://github.com/<nom_utilisateur>/<dépôt>/settings/actions/runners/new)
  2. Sélectionnez macOS comme image de runner et ARM64 comme architecture
  3. Suivez les commandes fournies pour télécharger et configurer le runner

GitHub Actions runner

Créez un fichier .env dans le répertoire _work du runner :

# Fichier _work/.env
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Exécutez le script run.sh dans votre répertoire de runner pour terminer la configuration.
  2. Vérifiez que le runner est actif et écoute les tâches dans le terminal et vérifiez les paramètres du dépôt GitHub pour l'association du runner et le statut Idle.

GitHub Actions runner

Étape 4 : Configurer Sudoers (Optionnel)

Si vos actions nécessitent des privilèges root, configurez le fichier sudoers :

sudo visudo

Ajoutez la ligne suivante :

gh-runner ALL=(ALL) NOPASSWD: ALL

Étape 5 : Utiliser le Runner dans les Workflows

Configurez votre workflow GitHub Actions pour utiliser le runner auto-hébergé :

name: Workflow exemple

on:
  workflow_dispatch:

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

Le runner est authentifié sur votre dépôt et étiqueté avec self-hosted, macOS, et ARM64. Utilisez-le dans vos workflows en spécifiant ces étiquettes dans le champ runs-on :

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

Bonnes Pratiques

  • Maintenez votre logiciel de runner à jour
  • Surveillez régulièrement les logs du runner pour détecter les problèmes
  • Utilisez des étiquettes spécifiques pour différents types de runners
  • Implémentez des mesures de sécurité appropriées
  • Considérez l'utilisation de plusieurs runners pour l'équilibrage de charge

Dépannage

Problèmes courants et solutions :

  1. Runner ne se connecte pas :

    • Vérifiez la connectivité réseau
    • Vérifiez la validité du token GitHub
    • Assurez-vous des permissions appropriées
  2. Échecs de build :

    • Vérifiez l'installation de Xcode
    • Vérifiez les dépendances requises
    • Examinez les logs du workflow
  3. Problèmes de permissions :

    • Vérifiez les permissions utilisateur
    • Vérifiez la configuration sudoers
    • Examinez les permissions du système de fichiers

Conclusion

Vous avez maintenant un runner GitHub Actions auto-hébergé configuré sur votre Mac Mini. Cette configuration vous donne plus de contrôle sur votre environnement CI/CD et vous permet d'exécuter efficacement des workflows spécifiques à macOS.

N'oubliez pas de maintenir régulièrement votre runner et de le tenir à jour avec les derniers correctifs de sécurité et versions de logiciels.

Application Native

Application native Roundfleet

Guide d'Installation Roundfleet

Roundfleet est une solution de gestion de flotte puissante conçue spécifiquement pour les environnements Mac Mini hébergés dans le cloud. En tant que fournisseur d'hébergement cloud Mac Mini, vous pouvez utiliser Roundfleet pour surveiller, gérer et optimiser toute votre flotte d'instances Mac virtualisées.

Ce guide d'installation vous accompagnera dans la configuration de la surveillance Roundfleet sur les systèmes macOS, Windows et Linux pour assurer une supervision complète de votre infrastructure cloud.

🍎 macOS

  • Téléchargez le fichier .dmg pour Mac ici
  • Double-cliquez sur le fichier .dmg téléchargé
  • Glissez l'app Roundfleet dans le dossier Applications
  • Éjectez le fichier .dmg
  • Ouvrez Préférences Système > Sécurité et confidentialité
    • Onglet Confidentialité > Accessibilité
    • Cochez Roundfleet pour autoriser la surveillance
  • Lancez Roundfleet depuis Applications
  • Le suivi démarre automatiquement

🪟 Windows

  • Téléchargez le fichier .exe pour Windows ici
  • Clic droit sur le fichier .exe > "Exécuter en tant qu'administrateur"
  • Suivez l'assistant d'installation
  • Acceptez les termes et conditions
  • Autorisez dans Windows Defender si demandé
  • Accordez les permissions de surveillance d'application
  • Lancez Roundfleet depuis le Menu Démarrer
  • L'application commence le suivi automatiquement

🐧 Linux

  • Téléchargez le paquet .deb (Ubuntu/Debian) ou .rpm (CentOS/RHEL) ici
  • Installez en utilisant votre gestionnaire de paquets
    • Ubuntu/Debian : sudo dpkg -i Roundfleet-linux.deb
    • CentOS/RHEL : sudo rpm -ivh Roundfleet-linux.rpm
  • Autorisez les permissions d'accès X11 si demandé
  • Ajoutez l'utilisateur aux groupes appropriés si nécessaire
  • Lancez Roundfleet depuis le menu Applications
  • L'application commence le suivi automatiquement

Note : Après l'installation sur tous les systèmes, connectez-vous avec vos identifiants Roundfleet pour synchroniser les données avec votre tableau de bord.