Guide

Nouvelles mises à jour et améliorations de Roundfleet.

Surveillance Réseau d'Entreprise sur macOS

Surveillez et contrôlez l'activité réseau sur vos appareils Roundfleet en utilisant les techniques avancées de surveillance réseau, l'analyse de bande passante et les contrôles de sécurité d'entreprise. Ce tutoriel fournit des outils complets pour implémenter la gestion réseau organisationnelle et les politiques de sécurité.

Comprendre la Surveillance Réseau macOS

macOS fournit plusieurs outils pour la surveillance de l'activité réseau :

  • lsof - Lister les fichiers ouverts et les connexions réseau
  • netstat - Afficher les connexions réseau et les tables de routage
  • nettop - Utilisation réseau en temps réel par processus
  • tcpdump - Capture et analyse de paquets
  • Little Snitch - Pare-feu au niveau application et moniteur réseau

Surveillance de Connexion Réseau Basique

Lister les Applications Connectées à Internet

#!/bin/bash

# Lister les processus uniques avec des connexions internet
lsof -nPi | cut -f 1 -d " " | uniq | tail -n +2

echo "Processus connectés à internet listés"

Connexions Réseau Détaillées

#!/bin/bash

# Afficher les informations détaillées de connexion réseau
echo "=== Connexions Réseau Actives ==="
lsof -nPi

echo -e "\n=== Statistiques Réseau ==="
netstat -an | head -20

Activité Réseau Spécifique par Processus

#!/bin/bash

# Surveiller l'activité réseau d'une application spécifique
APP_NAME="Chrome"

echo "Connexions réseau pour $APP_NAME:"
lsof -nPi | grep -i "$APP_NAME"

Système de Surveillance Réseau d'Entreprise

#!/bin/bash

# Système de Surveillance Réseau d'Entreprise Roundfleet
# Surveillance complète de l'activité réseau et gestion de sécurité

# Configuration
ROUNDFLEET_DIR="/etc/roundfleet"
MONITORING_DIR="$ROUNDFLEET_DIR/network_monitoring"
REPORTS_DIR="$ROUNDFLEET_DIR/reports"
COMPLIANCE_DIR="$ROUNDFLEET_DIR/compliance"
AUDIT_DIR="$ROUNDFLEET_DIR/audit"
LOG_FILE="/var/log/roundfleet_network_monitoring.log"
ALERTS_DIR="$ROUNDFLEET_DIR/alerts"

# Créer la structure de répertoires
create_directories() {
    local dirs=("$ROUNDFLEET_DIR" "$MONITORING_DIR" "$REPORTS_DIR" "$COMPLIANCE_DIR" "$AUDIT_DIR" "$ALERTS_DIR")
    for dir in "${dirs[@]}"; do
        [[ ! -d "$dir" ]] && mkdir -p "$dir"
    done
}

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

# Catégories d'Applications pour la Surveillance Réseau
declare -A APP_CATEGORIES=(
    ["apps_affaires"]="Slack,Zoom,Microsoft Teams,Office 365,Salesforce"
    ["outils_developpement"]="Xcode,Visual Studio Code,Docker,Git,npm"
    ["navigateurs"]="Chrome,Firefox,Safari,Edge"
    ["communication"]="Mail,Messages,FaceTime,Skype"
    ["stockage_cloud"]="Dropbox,Google Drive,OneDrive,iCloud"
    ["divertissement"]="Spotify,Netflix,YouTube,Steam"
    ["outils_securite"]="1Password,Little Snitch,Wireshark"
    ["services_systeme"]="locationd,cloudd,nsurlsessiond,trustd"
)

# Politiques de Surveillance Réseau
declare -A MONITORING_POLICIES=(
    ["surveillance_stricte"]="apps_affaires:autorise,outils_developpement:autorise,navigateurs:surveille,communication:autorise,stockage_cloud:surveille,divertissement:bloque,outils_securite:autorise,services_systeme:autorise"
    ["surveillance_equilibree"]="apps_affaires:autorise,outils_developpement:autorise,navigateurs:autorise,communication:autorise,stockage_cloud:autorise,divertissement:surveille,outils_securite:autorise,services_systeme:autorise"
    ["surveillance_minimale"]="apps_affaires:autorise,outils_developpement:autorise,navigateurs:autorise,communication:autorise,stockage_cloud:autorise,divertissement:autorise,outils_securite:autorise,services_systeme:autorise"
    ["focus_developpement"]="apps_affaires:autorise,outils_developpement:priorite,navigateurs:autorise,communication:autorise,stockage_cloud:autorise,divertissement:bloque,outils_securite:autorise,services_systeme:autorise"
    ["verrouillage_securite"]="apps_affaires:surveille,outils_developpement:surveille,navigateurs:surveille,communication:surveille,stockage_cloud:bloque,divertissement:bloque,outils_securite:autorise,services_systeme:autorise"
)

# Seuils de Bande Passante (en MB/s)
declare -A BANDWIDTH_THRESHOLDS=(
    ["critique"]=100
    ["eleve"]=50
    ["modere"]=20
    ["faible"]=5
)

# Obtenir l'activité réseau complète
get_network_activity() {
    local monitoring_level="$1"
    local output_file="$MONITORING_DIR/network_activity_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Début de la surveillance d'activité réseau: $monitoring_level"
    
    # Obtenir les connexions réseau basiques
    local connections=$(lsof -nPi 2>/dev/null | tail -n +2)
    local unique_processes=$(echo "$connections" | cut -f 1 -d " " | sort | uniq)
    
    # Obtenir les informations détaillées des processus
    local detailed_info=""
    while IFS= read -r process; do
        [[ -z "$process" ]] && continue
        
        local pids=$(pgrep -f "$process" 2>/dev/null | head -5)
        for pid in $pids; do
            local cpu_usage=$(ps -p "$pid" -o %cpu= 2>/dev/null | tr -d ' ')
            local mem_usage=$(ps -p "$pid" -o %mem= 2>/dev/null | tr -d ' ')
            local process_connections=$(echo "$connections" | grep "^$process" | wc -l)
            
            if [[ -n "$cpu_usage" && -n "$mem_usage" ]]; then
                detailed_info="$detailed_info{\"process\":\"$process\",\"pid\":$pid,\"cpu\":$cpu_usage,\"memory\":$mem_usage,\"connections\":$process_connections},"
            fi
        done
    done <<< "$unique_processes"
    
    # Supprimer la virgule de fin et formater en JSON
    detailed_info="${detailed_info%,}"
    
    cat > "$output_file" << EOF
{
  "metadonnees_surveillance": {
    "horodatage": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "nom_hote": "$(hostname)",
    "niveau_surveillance": "$monitoring_level",
    "version_rapport": "1.0"
  },
  "activite_reseau": {
    "total_processus": $(echo "$unique_processes" | wc -l),
    "connexions_actives": $(echo "$connections" | wc -l),
    "processus": [$detailed_info]
  },
  "metriques_systeme": {
    "charge_moyenne": "$(uptime | awk -F'load average:' '{print $2}' | tr -d ' ')",
    "pression_memoire": "$(memory_pressure 2>/dev/null || echo 'inconnu')",
    "interfaces_reseau": $(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
  }
}
EOF
    
    log_action "Rapport d'activité réseau sauvegardé: $output_file"
    echo "$output_file"
}

# Analyser l'utilisation de bande passante
analyze_bandwidth_usage() {
    local monitoring_duration="$1"
    local analysis_file="$MONITORING_DIR/bandwidth_analysis_$(date +%Y%m%d_%H%M%S).txt"
    
    log_action "Début de l'analyse de bande passante pour $monitoring_duration secondes"
    
    # Utiliser nettop pour la surveillance de bande passante
    timeout "$monitoring_duration" nettop -P -t wifi -t ethernet -l 1 > "$analysis_file" 2>/dev/null &
    local nettop_pid=$!
    
    sleep "$monitoring_duration"
    
    # Tuer nettop s'il fonctionne encore
    kill "$nettop_pid" 2>/dev/null
    
    # Analyser les données de bande passante
    local high_bandwidth_processes=""
    if [[ -f "$analysis_file" ]]; then
        # Extraire les processus avec une utilisation élevée de bande passante
        while IFS= read -r line; do
            [[ "$line" =~ ^[[:space:]]*[0-9] ]] || continue
            
            local process_name=$(echo "$line" | awk '{print $2}')
            local bytes_in=$(echo "$line" | awk '{print $3}' | sed 's/[^0-9]//g')
            local bytes_out=$(echo "$line" | awk '{print $4}' | sed 's/[^0-9]//g')
            
            # Convertir en MB/s (estimation approximative)
            local total_mb=$(( (bytes_in + bytes_out) / 1024 / 1024 / monitoring_duration ))
            
            if [[ $total_mb -gt ${BANDWIDTH_THRESHOLDS["modere"]} ]]; then
                high_bandwidth_processes="$high_bandwidth_processes$process_name:${total_mb}MB/s,"
            fi
        done < "$analysis_file"
    fi
    
    log_action "Analyse de bande passante terminée. Processus à usage élevé: ${high_bandwidth_processes%,}"
    echo "${high_bandwidth_processes%,}"
}

# Détection de menaces de sécurité
detect_security_threats() {
    local scan_mode="$1"
    local threats_file="$MONITORING_DIR/security_threats_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Début de la détection de menaces de sécurité: $scan_mode"
    
    # Obtenir les connexions réseau
    local connections=$(lsof -nPi 2>/dev/null)
    
    # Motifs suspects
    local suspicious_ports=("22" "23" "3389" "5900" "6667" "6697" "1337" "31337")
    local suspicious_domains=("*.tor" "*.onion" "tempmail" "guerrillamail" "10minutemail")
    local suspicious_processes=("nc" "netcat" "telnet" "ssh" "tor")
    
    local threats_detected=""
    local threat_count=0
    
    # Vérifier les ports suspects
    for port in "${suspicious_ports[@]}"; do
        local port_connections=$(echo "$connections" | grep ":$port" | wc -l)
        if [[ $port_connections -gt 0 ]]; then
            threats_detected="$threats_detected{\"type\":\"port_suspect\",\"details\":\"Le port $port a $port_connections connexions\",\"severite\":\"moyenne\"},"
            ((threat_count++))
        fi
    done
    
    # Vérifier les processus suspects
    for process in "${suspicious_processes[@]}"; do
        if pgrep -f "$process" >/dev/null 2>&1; then
            threats_detected="$threats_detected{\"type\":\"processus_suspect\",\"details\":\"Le processus $process est en cours d'exécution\",\"severite\":\"elevee\"},"
            ((threat_count++))
        fi
    done
    
    # Vérifier les motifs de connexion inhabituels
    local unique_external_ips=$(echo "$connections" | grep -E ":[0-9]+->.*:[0-9]+" | awk -F'->' '{print $2}' | cut -d':' -f1 | sort | uniq | wc -l)
    if [[ $unique_external_ips -gt 50 ]]; then
        threats_detected="$threats_detected{\"type\":\"anomalie_connexion\",\"details\":\"Nombre inhabituel de connexions externes: $unique_external_ips\",\"severite\":\"moyenne\"},"
        ((threat_count++))
    fi
    
    # Supprimer la virgule de fin
    threats_detected="${threats_detected%,}"
    
    cat > "$threats_file" << EOF
{
  "scan_securite": {
    "horodatage": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "mode_scan": "$scan_mode",
    "menaces_detectees": $threat_count,
    "menaces": [$threats_detected]
  },
  "resume_reseau": {
    "total_connexions": $(echo "$connections" | wc -l),
    "processus_uniques": $(echo "$connections" | cut -f1 -d' ' | sort | uniq | wc -l),
    "connexions_externes": $unique_external_ips
  }
}
EOF
    
    if [[ $threat_count -gt 0 ]]; then
        log_action "ALERTE SÉCURITÉ: $threat_count menaces détectées. Rapport: $threats_file"
        
        # Créer une alerte
        echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):MENACE_SECURITE:$threat_count menaces détectées" >> "$ALERTS_DIR/security_alerts.log"
    else
        log_action "Scan de sécurité terminé. Aucune menace détectée."
    fi
    
    echo "$threats_file"
}

# Appliquer une politique de surveillance réseau
apply_monitoring_policy() {
    local policy="$1"
    
    if [[ -z "${MONITORING_POLICIES[$policy]}" ]]; then
        log_action "ERREUR: Politique de surveillance inconnue: $policy"
        return 1
    fi
    
    log_action "Application de la politique de surveillance réseau: $policy"
    
    # Analyser la chaîne de politique
    IFS=',' read -ra policy_items <<< "${MONITORING_POLICIES[$policy]}"
    
    local policy_config="$MONITORING_DIR/active_policy.conf"
    echo "# Politique de Surveillance Réseau Roundfleet: $policy" > "$policy_config"
    echo "# Appliquée: $(date)" >> "$policy_config"
    echo "" >> "$policy_config"
    
    for item in "${policy_items[@]}"; do
        IFS=':' read -ra parts <<< "$item"
        local category="${parts[0]}"
        local action="${parts[1]}"
        
        echo "$category=$action" >> "$policy_config"
        
        case "$action" in
            "bloque")
                log_action "Configuration des blocages pour la catégorie: $category"
                # Dans une implémentation réelle, cela configurerait les règles de pare-feu
                ;;
            "surveille")
                log_action "Surveillance renforcée pour la catégorie: $category"
                ;;
            "priorite")
                log_action "Bande passante prioritaire pour la catégorie: $category"
                ;;
            "autorise")
                log_action "Accès standard pour la catégorie: $category"
                ;;
        esac
    done
    
    log_action "Politique de surveillance réseau '$policy' appliquée avec succès"
    
    # Générer un rapport de conformité de politique
    generate_compliance_report "$policy"
}

# Surveillance réseau en temps réel
start_realtime_monitoring() {
    local monitoring_interval="$1"
    local alert_threshold="$2"
    
    log_action "Début de la surveillance réseau temps réel (intervalle: ${monitoring_interval}s, seuil: $alert_threshold connexions)"
    
    local monitor_file="$MONITORING_DIR/realtime_monitor.log"
    
    while true; do
        local current_connections=$(lsof -nPi 2>/dev/null | wc -l)
        local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
        local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
        
        echo "$timestamp:$current_connections:$unique_processes" >> "$monitor_file"
        
        # Vérifier le seuil d'alerte
        if [[ $current_connections -gt $alert_threshold ]]; then
            log_action "ALERTE: Activité réseau élevée détectée - $current_connections connexions"
            echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):ACTIVITE_ELEVEE:$current_connections connexions" >> "$ALERTS_DIR/activity_alerts.log"
        fi
        
        sleep "$monitoring_interval"
    done
}

# Contrôle d'accès réseau
control_network_access() {
    local action="$1"
    local target="$2"
    local reason="$3"
    
    log_action "Contrôle d'accès réseau: $action pour $target (Raison: $reason)"
    
    case "$action" in
        "bloquer_processus")
            # Tuer les processus connectés au réseau
            local pids=$(pgrep -f "$target" 2>/dev/null)
            for pid in $pids; do
                if kill -TERM "$pid" 2>/dev/null; then
                    log_action "Processus terminé: $target (PID: $pid)"
                fi
            done
            ;;
        "bloquer_domaine")
            # Ajouter au fichier hosts pour blocage
            if ! grep -q "127.0.0.1 $target" /etc/hosts; then
                echo "127.0.0.1 $target" >> /etc/hosts
                log_action "Domaine bloqué: $target"
            fi
            ;;
        "debloquer_domaine")
            # Supprimer du fichier hosts
            sed -i "" "/127.0.0.1 $target/d" /etc/hosts
            log_action "Domaine débloqué: $target"
            ;;
        "limiter_bande_passante")
            # Cela nécessiterait une intégration avec des outils de shaping de trafic
            log_action "Limitation de bande passante demandée pour: $target (Non implémenté - nécessite pfctl ou similaire)"
            ;;
    esac
    
    # Enregistrer l'action dans le journal d'audit
    echo "$(date -u +%Y-%m-%dT%H:%M:%SZ):$action:$target:$reason:$(whoami)" >> "$AUDIT_DIR/network_control_actions.log"
}

# Générer un rapport de conformité complet
generate_compliance_report() {
    local policy="$1"
    local report_file="$REPORTS_DIR/network_monitoring_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    # Obtenir l'activité réseau actuelle
    local active_connections=$(lsof -nPi 2>/dev/null | wc -l)
    local unique_processes=$(lsof -nPi 2>/dev/null | cut -f1 -d' ' | sort | uniq | wc -l)
    
    # Compter les alertes
    local security_alerts=0
    local activity_alerts=0
    
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        security_alerts=$(wc -l < "$ALERTS_DIR/security_alerts.log")
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        activity_alerts=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
    fi
    
    cat > "$report_file" << EOF
{
  "metadonnees_rapport": {
    "horodatage": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "nom_hote": "$(hostname)",
    "politique_appliquee": "$policy",
    "version_rapport": "1.0"
  },
  "statut_surveillance_reseau": {
    "connexions_actives": $active_connections,
    "processus_surveilles": $unique_processes,
    "alertes_securite": $security_alerts,
    "alertes_activite": $activity_alerts,
    "surveillance_active": $([ -f "$MONITORING_DIR/realtime_monitor.log" ] && echo "true" || echo "false")
  },
  "politique_securite": {
    "nom": "$policy",
    "categories_surveillees": $(echo "${!APP_CATEGORIES[@]}" | wc -w),
    "cadres_conformite": ["SOX", "HIPAA", "NIST", "ISO27001", "PCI-DSS"]
  },
  "sante_reseau": {
    "surveillance_bande_passante": $(command -v nettop >/dev/null && echo "true" || echo "false"),
    "pare_feu_actif": $(pfctl -s info 2>/dev/null | grep -q "Status: Enabled" && echo "true" || echo "false"),
    "filtrage_dns": $(networksetup -getdnsservers Wi-Fi | grep -q "208.67" && echo "true" || echo "false"),
    "vpn_detecte": $(ifconfig | grep -q "utun" && echo "true" || echo "false")
  },
  "metriques_conformite": {
    "violations_politique": 0,
    "tentatives_exfiltration_donnees": 0,
    "connexions_non_autorisees": $security_alerts,
    "violations_bande_passante": 0
  }
}
EOF
    
    log_action "Rapport de conformité surveillance réseau généré: $report_file"
    echo "Rapport sauvegardé vers: $report_file"
}

# Vérification de santé et validation système
perform_health_check() {
    echo "=== Vérification de Santé Surveillance Réseau Roundfleet ==="
    
    # Vérifier les outils de surveillance réseau
    local tools=("lsof" "netstat" "nettop" "networksetup")
    for tool in "${tools[@]}"; do
        if command -v "$tool" >/dev/null 2>&1; then
            echo "✓ $tool: Disponible"
        else
            echo "✗ $tool: Manquant"
        fi
    done
    
    # Vérifier les connexions actives
    local connections=$(lsof -nPi 2>/dev/null | wc -l)
    echo "✓ Connexions réseau actives: $connections"
    
    # Vérifier les fichiers de surveillance
    if [[ -f "$MONITORING_DIR/active_policy.conf" ]]; then
        local active_policy=$(grep -v "^#" "$MONITORING_DIR/active_policy.conf" | head -1)
        echo "✓ Politique de surveillance active: $active_policy"
    else
        echo "○ Aucune politique de surveillance active"
    fi
    
    # Vérifier les alertes
    local total_alerts=0
    if [[ -f "$ALERTS_DIR/security_alerts.log" ]]; then
        local security_count=$(wc -l < "$ALERTS_DIR/security_alerts.log")
        total_alerts=$((total_alerts + security_count))
    fi
    
    if [[ -f "$ALERTS_DIR/activity_alerts.log" ]]; then
        local activity_count=$(wc -l < "$ALERTS_DIR/activity_alerts.log")
        total_alerts=$((total_alerts + activity_count))
    fi
    
    if [[ $total_alerts -gt 0 ]]; then
        echo "⚠️  Total alertes: $total_alerts"
    else
        echo "✓ Aucune alerte active"
    fi
    
    # Vérifier la santé réseau système
    local network_interfaces=$(networksetup -listallhardwareports | grep "Hardware Port" | wc -l)
    echo "✓ Interfaces réseau: $network_interfaces"
    
    # Vérifier la configuration DNS
    local dns_servers=$(networksetup -getdnsservers Wi-Fi 2>/dev/null | head -1)
    echo "✓ Serveur DNS: $dns_servers"
}

# Fonction de déploiement de flotte
deploy_to_fleet() {
    local policy="$1"
    local fleet_file="$2"
    
    if [[ ! -f "$fleet_file" ]]; then
        log_action "ERREUR: Fichier de flotte non trouvé: $fleet_file"
        return 1
    fi
    
    log_action "Début du déploiement de flotte de la politique de surveillance réseau: $policy"
    
    while IFS= read -r host; do
        [[ -z "$host" || "$host" =~ ^#.*$ ]] && continue
        
        echo "Déploiement vers: $host"
        
        # Copier ce script vers l'hôte distant et l'exécuter
        ssh "$host" "bash -s" << EOF
#!/bin/bash
# Déploiement distant de la politique de surveillance réseau: $policy

# Créer les répertoires
mkdir -p /etc/roundfleet/{network_monitoring,reports,compliance,audit,alerts}

# Appliquer la politique (simplifié pour l'exécution distante)
$(declare -p APP_CATEGORIES)
$(declare -p MONITORING_POLICIES)
$(type apply_monitoring_policy | sed '1d')

apply_monitoring_policy "$policy"
EOF
        
        if [[ $? -eq 0 ]]; then
            log_action "Déploiement réussi vers: $host"
        else
            log_action "Échec du déploiement vers: $host"
        fi
        
    done < "$fleet_file"
    
    log_action "Déploiement de flotte terminé"
}

# Fonction d'exécution principale
main() {
    create_directories
    
    case "${1:-}" in
        "surveiller_activite")
            get_network_activity "${2:-standard}"
            ;;
        "analyser_bande_passante")
            analyze_bandwidth_usage "${2:-30}"
            ;;
        "detecter_menaces")
            detect_security_threats "${2:-standard}"
            ;;
        "appliquer_politique")
            apply_monitoring_policy "$2"
            ;;
        "surveillance_temps_reel")
            start_realtime_monitoring "${2:-10}" "${3:-100}"
            ;;
        "controler_acces")
            control_network_access "$2" "$3" "${4:-manuel}"
            ;;
        "verification_sante")
            perform_health_check
            ;;
        "rapport")
            generate_compliance_report "${2:-manuel}"
            ;;
        "deployer")
            deploy_to_fleet "$2" "$3"
            ;;
        "aide"|*)
            echo "Système de Surveillance Réseau d'Entreprise Roundfleet"
            echo ""
            echo "Usage: $0 <commande> [options]"
            echo ""
            echo "Commandes:"
            echo "  surveiller_activite [niveau]              - Surveiller l'activité réseau (standard|detaille|securite)"
            echo "  analyser_bande_passante [duree]           - Analyser l'utilisation de bande passante pour durée en secondes"
            echo "  detecter_menaces [mode]                   - Détecter les menaces de sécurité (standard|strict|paranoiaque)"
            echo "  appliquer_politique <politique>           - Appliquer une politique de surveillance (surveillance_stricte|surveillance_equilibree|surveillance_minimale|focus_developpement|verrouillage_securite)"
            echo "  surveillance_temps_reel [intervalle] [seuil] - Démarrer la surveillance temps réel"
            echo "  controler_acces <action> <cible> [raison] - Contrôler l'accès réseau (bloquer_processus|bloquer_domaine|debloquer_domaine|limiter_bande_passante)"
            echo "  verification_sante                        - Effectuer une vérification de santé système"
            echo "  rapport [politique]                       - Générer un rapport de conformité"
            echo "  deployer <politique> <fichier_flotte>     - Déployer une politique vers la flotte"
            echo ""
            echo "Exemples:"
            echo "  $0 surveiller_activite detaille"
            echo "  $0 analyser_bande_passante 60"
            echo "  $0 detecter_menaces strict"
            echo "  $0 appliquer_politique surveillance_stricte"
            echo "  $0 controler_acces bloquer_domaine site-malveillant.com"
            echo "  $0 verification_sante"
            ;;
    esac
}

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

Catégories de Surveillance Réseau

Le système d'entreprise surveille les applications dans différentes catégories :

CatégorieApplicationsNiveau de Surveillance
Apps AffairesSlack, Zoom, Microsoft Teams, Office 365Surveillance standard
Outils DéveloppementXcode, Visual Studio Code, Docker, GitJournalisation renforcée
NavigateursChrome, Firefox, Safari, EdgeAnalyse de trafic
CommunicationMail, Messages, FaceTime, SkypeScan de sécurité
Stockage CloudDropbox, Google Drive, OneDriveSurveillance transfert données
DivertissementSpotify, Netflix, YouTube, SteamLimitation bande passante
Outils Sécurité1Password, Little Snitch, WiresharkAccès prioritaire
Services Systèmelocationd, cloudd, nsurlsessiondSurveillance santé système

Analyse Réseau Avancée

Surveillance Bande Passante Temps Réel

# Surveiller l'utilisation de bande passante pendant 60 secondes
./surveillance_reseau.sh analyser_bande_passante 60

# Vérifier les processus à haute bande passante
nettop -P -t wifi -l 1 | head -20

Détection de Menaces de Sécurité

# Exécuter un scan de menaces de sécurité
./surveillance_reseau.sh detecter_menaces strict

# Vérifier les connexions suspectes
lsof -nPi | grep -E ":(22|23|3389|5900|6667)"

Analyse de Connexions

# Analyse détaillée des connexions
lsof -nPi | awk '{print $1, $8, $9}' | sort | uniq -c | sort -nr

# Surveiller une application spécifique
lsof -nPi | grep -i "chrome"

Implémentation de Politiques

Appliquer une Politique de Surveillance d'Entreprise

# Surveillance stricte pour environnements sécurisés
./surveillance_reseau.sh appliquer_politique surveillance_stricte

# Surveillance équilibrée pour usage général
./surveillance_reseau.sh appliquer_politique surveillance_equilibree

# Surveillance axée développement
./surveillance_reseau.sh appliquer_politique focus_developpement

Contrôle d'Accès Réseau

# Bloquer un processus suspect
./surveillance_reseau.sh controler_acces bloquer_processus "app_suspecte" "violation_securite"

# Bloquer un domaine malveillant
./surveillance_reseau.sh controler_acces bloquer_domaine "site-malveillant.com" "menace_detectee"

# Débloquer un domaine après vérification
./surveillance_reseau.sh controler_acces debloquer_domaine "exemple.com" "faux_positif"

Fonctionnalités d'Entreprise

Réponse Automatisée aux Menaces

Le système peut automatiquement répondre aux menaces :

  • Bloquer les processus suspects
  • Mettre en quarantaine les connexions réseau
  • Alerter les équipes de sécurité
  • Générer des rapports d'incidents

Gestion de Bande Passante

Surveiller et contrôler l'utilisation de bande passante :

  • Identifier les applications consommatrices de bande passante
  • Implémenter des règles de qualité de service (QoS)
  • Générer des rapports d'utilisation
  • Alerter sur la consommation excessive

Surveillance de Conformité

Suivre l'activité réseau pour la conformité :

  • Journaliser toutes les connexions réseau
  • Surveiller les volumes de transfert de données
  • Détecter les violations de politique
  • Générer des rapports d'audit

Considérations de Sécurité Importantes

  • La surveillance temps réel nécessite des ressources système appropriées
  • L'analyse réseau doit respecter les politiques de confidentialité des utilisateurs
  • La détection de menaces peut générer des faux positifs nécessitant validation
  • Les contrôles d'accès doivent inclure des procédures de contournement d'urgence
  • La journalisation d'audit doit être protégée contre l'accès non autorisé

Conformité et Rapports

Le système d'entreprise fournit des pistes d'audit complètes pour :

  • Conformité SOX - Contrôles d'accès réseau données financières
  • Exigences HIPAA - Surveillance transmission informations santé
  • Standards PCI-DSS - Sécurité réseau industrie cartes paiement
  • Cadre NIST - Standards surveillance réseau cybersécurité
  • ISO 27001 - Gestion réseau sécurité information

Tests et Validation

Avant le déploiement en entreprise :

  1. Tester la précision de surveillance avec des activités réseau connues
  2. Vérifier l'efficacité de détection de menaces et les taux de faux positifs
  3. Confirmer que l'application de politiques fonctionne comme prévu
  4. Tester les procédures d'urgence et mécanismes de contournement
  5. Valider la complétude et précision des rapports de conformité

Ce système complet transforme la surveillance réseau basique en une plateforme de sécurité et gestion de niveau entreprise avec détection avancée de menaces, application de politiques et capacités de déploiement de flotte.

Récupérer les Informations Réseau sur macOS

Collectez des informations réseau détaillées de vos appareils Roundfleet en utilisant des outils en ligne de commande. Ce tutoriel couvre la découverte d'adresses MAC, la configuration IP, la surveillance des ports et les diagnostics réseau pour une gestion complète de flotte.

Comprendre les Informations Réseau macOS

macOS fournit plusieurs utilitaires en ligne de commande pour la collecte d'informations réseau :

  • networksetup - Gestion des ports matériels et configuration réseau
  • ifconfig - Configuration et statut des interfaces réseau
  • netstat - Connexions réseau et informations de ports
  • arp - Gestion de la table du protocole de résolution d'adresse
  • ipconfig - Configuration des adresses IP et DHCP

Récupérer les Adresses MAC

Lister Tous les Ports Matériels

#!/bin/bash

# Afficher tous les ports matériels réseau et leurs adresses MAC
networksetup -listallhardwareports

echo "Informations des ports matériels récupérées avec succès"

Obtenir l'Adresse MAC d'une Interface Spécifique

#!/bin/bash

# Obtenir l'adresse MAC pour une interface spécifique (Wi-Fi)
echo "Adresse MAC de l'Interface Wi-Fi (en0) :"
networksetup -getmacaddress en0

echo -e "\nAdresse MAC de l'Interface Ethernet (en1) :"
networksetup -getmacaddress en1

echo -e "\nAdresse MAC du Pont Thunderbolt (bridge0) :"
networksetup -getmacaddress bridge0 2>/dev/null || echo "Pont Thunderbolt non disponible"

Rapport Complet d'Adresses MAC

#!/bin/bash

# Générer un rapport détaillé d'adresses MAC
echo "=== Rapport Matériel Réseau Roundfleet ==="
echo "Appareil : $(hostname)"
echo "Date : $(date)"
echo "========================================="

# Obtenir tous les ports matériels
echo -e "\n📡 Inventaire Matériel Réseau :"
networksetup -listallhardwareports

echo -e "\n🔍 Détails des Interfaces Principales :"
echo "Wi-Fi (en0) : $(networksetup -getmacaddress en0 | awk '{print $3}')"
echo "Ethernet (en1) : $(networksetup -getmacaddress en1 | awk '{print $3}' 2>/dev/null || echo 'Non disponible')"

# Vérifier les interfaces supplémentaires
echo -e "\n🌐 Interfaces Supplémentaires :"
for i in {2..5}; do
    mac_addr=$(networksetup -getmacaddress en$i 2>/dev/null | awk '{print $3}')
    if [[ -n "$mac_addr" && "$mac_addr" != "not" ]]; then
        echo "en$i : $mac_addr"
    fi
done

Découvrir les Adresses IP

Récupération Basique d'Adresses IP

#!/bin/bash

# Obtenir l'adresse IP pour l'interface Wi-Fi
WIFI_IP=$(ipconfig getifaddr en0 2>/dev/null)
ETHERNET_IP=$(ipconfig getifaddr en1 2>/dev/null)

echo "Adresses IP Réseau :"
echo "Wi-Fi (en0) : ${WIFI_IP:-Non connecté}"
echo "Ethernet (en1) : ${ETHERNET_IP:-Non connecté}"

Configuration IP Complète

#!/bin/bash

# Rapport détaillé de configuration IP
echo "=== Rapport de Configuration IP Roundfleet ==="
echo "Appareil : $(hostname)"
echo "Horodatage : $(date)"
echo "========================================"

# Interfaces réseau actives
echo -e "\n🌐 Interfaces Réseau Actives :"
for interface in en0 en1 en2 en3; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        echo "$interface : $ip_addr"
        
        # Obtenir des détails supplémentaires pour les interfaces actives
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        router=$(ipconfig getoption $interface router 2>/dev/null)
        dns_servers=$(ipconfig getoption $interface domain_name_server 2>/dev/null)
        
        echo "  Sous-réseau : ${subnet_mask:-N/A}"
        echo "  Passerelle : ${router:-N/A}"
        echo "  DNS : ${dns_servers:-N/A}"
        echo ""
    fi
done

# Adresse IP publique
echo "🌍 Adresse IP Externe :"
curl -s ifconfig.me 2>/dev/null || echo "Impossible de récupérer l'IP externe"

Statut des Interfaces Réseau

#!/bin/bash

# Surveiller le statut des interfaces réseau
echo "=== Surveillance du Statut des Interfaces Réseau ==="

# Obtenir les statistiques d'interface
echo -e "\n📊 Statistiques des Interfaces :"
ifconfig | grep -E "(en[0-9]:|inet |status:|media:)" | while read line; do
    echo "$line"
done

echo -e "\n🔄 Informations de Bail DHCP :"
for interface in en0 en1; do
    lease_info=$(ipconfig getpacket $interface 2>/dev/null)
    if [[ -n "$lease_info" ]]; then
        echo "Interface $interface :"
        echo "$lease_info" | grep -E "(lease_time|server_identifier|domain_name)"
        echo ""
    fi
done

Analyser la Configuration Réseau

Vue d'Ensemble Réseau Complète

#!/bin/bash

# Analyse complète de la configuration réseau
echo "=== Vue d'Ensemble Réseau Complète ==="
ifconfig

echo -e "\n🔍 Résumé Réseau :"
ifconfig | grep -E "^[a-z]" | while read line; do
    interface=$(echo $line | cut -d: -f1)
    status=$(ifconfig $interface | grep "status:" | cut -d' ' -f2-)
    echo "$interface : ${status:-actif}"
done

Services Réseau et DNS

#!/bin/bash

# Configuration des services réseau et DNS
echo "=== Configuration des Services Réseau ==="

echo "🌐 Configuration DNS :"
echo "Serveurs DNS Système :"
scutil --dns | grep "nameserver" | head -5

echo -e "\n📡 Services Réseau :"
networksetup -listallnetworkservices

echo -e "\n🔍 Détails du Service Réseau Actif :"
active_service=$(networksetup -listallnetworkservices | grep -v "asterisk" | head -2 | tail -1)
if [[ -n "$active_service" ]]; then
    echo "Service : $active_service"
    networksetup -getinfo "$active_service"
fi

Informations de Sous-réseau et Routage

#!/bin/bash

# Informations de masque de sous-réseau et routage
echo "=== Informations de Routage et Sous-réseau ==="

echo "🛣️  Table de Routage :"
netstat -rn | head -10

echo -e "\n🔍 Détails de Sous-réseau d'Interface :"
for interface in en0 en1; do
    ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
    if [[ -n "$ip_addr" ]]; then
        subnet_mask=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
        echo "$interface : $ip_addr/${subnet_mask:-inconnu}"
    fi
done

Surveiller les Informations de Ports

Connexions TCP Actives

#!/bin/bash

# Afficher les connexions TCP actives
echo "=== Connexions TCP Actives ==="
netstat -ap TCP

echo -e "\n📊 Résumé des Connexions :"
echo "Total connexions : $(netstat -ap TCP | grep -c ESTABLISHED)"
echo "Ports en écoute : $(netstat -ap TCP | grep -c LISTEN)"
echo "Connexions time-wait : $(netstat -ap TCP | grep -c TIME_WAIT)"

Analyse des Ports en Écoute

#!/bin/bash

# Analyser les ports en écoute
echo "=== Analyse des Ports en Écoute ==="

echo "🔍 Tous les Ports en Écoute :"
netstat -a | grep -i "LISTEN"

echo -e "\n📋 Résumé des Ports en Écoute :"
netstat -a | grep -i "LISTEN" | awk '{print $4}' | cut -d. -f2 | sort -n | uniq -c | sort -nr

echo -e "\n🔒 Ports Pertinents pour la Sécurité :"
netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995|587|25|53|21|23) "

Script de Surveillance des Ports

#!/bin/bash

# Surveillance complète des ports
LOG_FILE="/var/log/roundfleet_ports.log"

monitor_ports() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    {
        echo "=== Rapport de Surveillance des Ports ==="
        echo "Horodatage : $timestamp"
        echo "Appareil : $(hostname)"
        echo "================================"
        
        echo -e "\n🔍 Ports en Écoute Actuels :"
        netstat -a | grep -i "LISTEN" | head -20
        
        echo -e "\n📊 Statistiques de Connexion :"
        echo "ESTABLISHED : $(netstat -ap TCP | grep -c ESTABLISHED)"
        echo "LISTEN : $(netstat -ap TCP | grep -c LISTEN)"
        echo "TIME_WAIT : $(netstat -ap TCP | grep -c TIME_WAIT)"
        echo "CLOSE_WAIT : $(netstat -ap TCP | grep -c CLOSE_WAIT)"
        
        echo -e "\n🚨 Connexions Suspectes :"
        netstat -ap TCP | grep -E ":(6667|6697|8080|9050|4444|31337)" || echo "Aucune détectée"
        
    } | tee -a "$LOG_FILE"
}

# Exécuter la surveillance
monitor_ports

Afficher la Table ARP

Informations ARP Basiques

#!/bin/bash

# Afficher la table du protocole de résolution d'adresse
arp -a

echo "Table ARP récupérée avec succès"

Analyse Détaillée ARP

#!/bin/bash

# Analyse complète de la table ARP
echo "=== Analyse de la Table ARP ==="
echo "Appareil : $(hostname)"
echo "Date : $(date)"
echo "=========================="

echo -e "\n🔍 Table ARP Complète :"
arp -a

echo -e "\n📊 Statistiques ARP :"
total_entries=$(arp -a | wc -l)
incomplete_entries=$(arp -a | grep -c "incomplete")
complete_entries=$((total_entries - incomplete_entries))

echo "Total entrées ARP : $total_entries"
echo "Entrées complètes : $complete_entries"
echo "Entrées incomplètes : $incomplete_entries"

echo -e "\n🌐 Voisins Réseau :"
arp -a | head -10 | while read line; do
    hostname=$(echo $line | cut -d' ' -f1)
    ip=$(echo $line | cut -d'(' -f2 | cut -d')' -f1)
    mac=$(echo $line | cut -d' ' -f4)
    echo "$ip -> $mac ($hostname)"
done

Vérification de Sécurité ARP

#!/bin/bash

# Analyse de sécurité de la table ARP
echo "=== Analyse de Sécurité ARP ==="

# Vérifier les adresses MAC dupliquées (potentiel ARP spoofing)
echo "🔒 Vérification des Adresses MAC Dupliquées :"
arp -a | awk '{print $4}' | sort | uniq -d | while read mac; do
    if [[ -n "$mac" ]]; then
        echo "⚠️  MAC dupliquée détectée : $mac"
        arp -a | grep "$mac"
    fi
done

# Vérifier les modèles suspects
echo -e "\n🚨 Alertes de Sécurité :"
suspicious_count=$(arp -a | grep -c "incomplete")
if [[ $suspicious_count -gt 10 ]]; then
    echo "⚠️  Nombre élevé d'entrées ARP incomplètes : $suspicious_count"
fi

# Analyse des fournisseurs réseau
echo -e "\n🏢 Analyse des Fournisseurs Réseau :"
arp -a | grep -E "([0-9a-f]{2}:){5}[0-9a-f]{2}" | awk '{print $4}' | cut -d: -f1-3 | sort | uniq -c | sort -nr | head -5

Script de Surveillance Réseau d'Entreprise

#!/bin/bash

# Suite de Surveillance Réseau d'Entreprise Roundfleet
LOG_FILE="/var/log/roundfleet_network.log"
REPORT_FILE="/tmp/network_report_$(date +%Y%m%d_%H%M%S).txt"

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

# Générer un rapport réseau complet
generate_network_report() {
    {
        echo "Rapport d'Évaluation Réseau Roundfleet"
        echo "Généré : $(date)"
        echo "Appareil : $(hostname)"
        echo "Utilisateur : $(whoami)"
        echo "Version OS : $(sw_vers -productVersion)"
        echo "=========================================="
        echo ""
        
        # Inventaire matériel
        echo "🔧 Matériel Réseau :"
        networksetup -listallhardwareports
        echo ""
        
        # Configuration IP
        echo "🌐 Configuration IP :"
        for interface in en0 en1 en2; do
            ip_addr=$(ipconfig getifaddr $interface 2>/dev/null)
            if [[ -n "$ip_addr" ]]; then
                echo "$interface : $ip_addr"
                mac_addr=$(networksetup -getmacaddress $interface | awk '{print $3}')
                echo "  MAC : $mac_addr"
                
                subnet=$(ipconfig getoption $interface subnet_mask 2>/dev/null)
                router=$(ipconfig getoption $interface router 2>/dev/null)
                echo "  Sous-réseau : ${subnet:-N/A}"
                echo "  Passerelle : ${router:-N/A}"
                echo ""
            fi
        done
        
        # Services réseau
        echo "📡 Services Réseau :"
        networksetup -listallnetworkservices | grep -v "asterisk"
        echo ""
        
        # Configuration DNS
        echo "🔍 Configuration DNS :"
        scutil --dns | grep "nameserver" | head -3
        echo ""
        
        # Évaluation de sécurité
        echo "🔒 Évaluation de Sécurité :"
        listening_ports=$(netstat -a | grep -c "LISTEN")
        established_connections=$(netstat -ap TCP | grep -c ESTABLISHED)
        echo "Ports en écoute : $listening_ports"
        echo "Connexions actives : $established_connections"
        
        # Vérifier les ports de sécurité courants
        security_ports=$(netstat -a | grep -i "LISTEN" | grep -E ":(22|80|443|993|995)" | wc -l)
        echo "Ports pertinents pour la sécurité : $security_ports"
        
        echo ""
        echo "Rapport terminé à : $(date)"
        
    } > "$REPORT_FILE"
    
    echo "📊 Rapport réseau généré : $REPORT_FILE"
}

# Test de connectivité réseau
test_connectivity() {
    echo "=== Test de Connectivité Réseau ==="
    
    # Test de résolution DNS
    if nslookup google.com > /dev/null 2>&1; then
        echo "✅ Résolution DNS : Fonctionnelle"
    else
        echo "❌ Résolution DNS : Échec"
    fi
    
    # Test de connectivité internet
    if ping -c 1 8.8.8.8 > /dev/null 2>&1; then
        echo "✅ Connectivité internet : Fonctionnelle"
    else
        echo "❌ Connectivité internet : Échec"
    fi
    
    # Test de passerelle locale
    gateway=$(route -n get default | grep gateway | awk '{print $2}')
    if [[ -n "$gateway" ]] && ping -c 1 "$gateway" > /dev/null 2>&1; then
        echo "✅ Connectivité passerelle : Fonctionnelle ($gateway)"
    else
        echo "❌ Connectivité passerelle : Échec"
    fi
}

# Exécution principale
main() {
    log_action "=== Surveillance Réseau Roundfleet Démarrée ==="
    
    generate_network_report
    echo ""
    test_connectivity
    
    log_action "Surveillance réseau terminée. Rapport : $REPORT_FILE"
}

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

Référence des Informations Réseau

Interfaces Réseau Courantes

InterfaceDescriptionUsage Courant
en0Interface réseau principaleConnexion Wi-Fi
en1Interface secondaireConnexion Ethernet
en2-en5Interfaces supplémentairesAdaptateurs USB, Thunderbolt
lo0Interface de bouclageCommunication système locale
bridge0Pont ThunderboltConnexions appareil-à-appareil
utun0-utun3Interfaces tunnelConnexions VPN

Référence Rapide des Commandes Réseau

# Obtenir l'IP d'interface
ipconfig getifaddr en0

# Obtenir la configuration d'interface
ipconfig getoption en0 subnet_mask
ipconfig getoption en0 router
ipconfig getoption en0 domain_name_server

# Matériel réseau
networksetup -listallhardwareports
networksetup -getmacaddress en0

# Statut d'interface
ifconfig en0
ifconfig -a

# Connexions réseau
netstat -rn          # Table de routage
netstat -i           # Statistiques d'interface
netstat -ap TCP      # Connexions TCP

# Opérations ARP
arp -a               # Afficher la table ARP
arp -d hostname      # Supprimer l'entrée ARP

Diagnostics Réseau Avancés

Test de Performance Réseau

#!/bin/bash

# Diagnostics de performance réseau
echo "=== Diagnostics de Performance Réseau ==="

# Statistiques d'interface
echo "📊 Statistiques d'Interface :"
netstat -i

# Surveillance de bande passante
echo -e "\n🚀 Activité Réseau (10 secondes) :"
if command -v nettop >/dev/null 2>&1; then
    timeout 10 nettop -l 1 -J bytes_in,bytes_out -P
else
    echo "nettop non disponible, utilisation de netstat"
    netstat -i
fi

# Test de latence
echo -e "\n⏱️  Tests de Latence :"
echo "DNS Google (8.8.8.8) :"
ping -c 3 8.8.8.8 | tail -1

echo "DNS Cloudflare (1.1.1.1) :"
ping -c 3 1.1.1.1 | tail -1

Informations Réseau Sans Fil

#!/bin/bash

# Informations détaillées du réseau sans fil
echo "=== Analyse du Réseau Sans Fil ==="

# Informations Wi-Fi actuelles
current_wifi=$(networksetup -getairportnetwork en0)
echo "Wi-Fi actuel : $current_wifi"

# Statut d'alimentation Wi-Fi
wifi_power=$(networksetup -getairportpower en0)
echo "Alimentation Wi-Fi : $wifi_power"

# Réseaux disponibles (nécessite des privilèges admin)
echo -e "\n📡 Réseaux Disponibles :"
if [[ $EUID -eq 0 ]]; then
    airport -s 2>/dev/null || echo "Utilitaire Airport non disponible"
else
    echo "Privilèges admin requis pour le scan réseau"
fi

# Détails de l'interface Wi-Fi
echo -e "\n🔍 Détails de l'Interface Wi-Fi :"
ifconfig en0 | grep -E "(inet|ether|status)"

Notes Importantes

  • Noms d'interface peuvent varier entre les versions macOS et le matériel
  • Privilèges administrateur requis pour certaines opérations réseau
  • Implications de sécurité - Surveiller régulièrement les ports ouverts et connexions
  • Impact sur les performances - Les scripts de surveillance réseau peuvent affecter les performances système
  • Considérations de confidentialité - Les tables ARP contiennent des informations sur les voisins réseau

Dépannage

Problèmes Réseau Courants

Pas d'Adresse IP :

# Renouveler le bail DHCP
sudo ipconfig set en0 DHCP

Problèmes de Résolution DNS :

# Vider le cache DNS
sudo dscacheutil -flushcache

Interface Non Responsive :

# Réinitialiser l'interface réseau
sudo ifconfig en0 down
sudo ifconfig en0 up

N'oubliez pas de tester ces scripts sur des appareils individuels avant de les déployer dans votre environnement Roundfleet.

Personnalisation de la Barre de Menu et Gestion des Icônes sur macOS

Personnalisez l'apparence de la barre de menu et gérez les icônes système sur vos appareils Roundfleet. Ce tutoriel couvre le contrôle de visibilité des icônes, l'optimisation de l'interface utilisateur et la gestion de barre de menu d'entreprise pour une expérience utilisateur améliorée et une cohérence organisationnelle.

Comprendre la Gestion de la Barre de Menu

La barre de menu macOS contient divers indicateurs système et icônes d'accès rapide :

  • Indicateurs réseau - Statut VPN, Wi-Fi, Bluetooth
  • Moniteurs système - Batterie, volume, date/heure
  • Icônes d'applications - Indicateurs de statut d'applications tierces
  • Contrôles utilisateur - Spotlight, Centre de Contrôle, Siri
  • Outils d'entreprise - Agents MDM, logiciels de sécurité

Gestion Basique des Icônes VPN

Masquer l'Icône VPN de la Barre de Menu

#!/bin/bash

# Masquer l'icône VPN de la barre de menu
hide_vpn_icon() {
    echo "=== Masquage de l'Icône VPN de la Barre de Menu ==="
    
    # Obtenir l'utilisateur actuel
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ Aucune session utilisateur active trouvée"
        return 1
    fi
    
    echo "👤 Utilisateur actuel : $currentUser"
    
    # Fonction pour exécuter des commandes en tant qu'utilisateur actuel
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Supprimer l'extra de menu VPN
    if runAsUser /usr/libexec/PlistBuddy -c 'delete menuExtras: "/System/Library/CoreServices/Menu Extras/VPN.menu"' "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ Entrée menu VPN supprimée"
    else
        echo "⚠️  Entrée menu VPN non trouvée ou déjà supprimée"
    fi
    
    # Redémarrer les services système pour appliquer les changements
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "🔄 Interface système actualisée"
    echo "✅ Icône VPN masquée de la barre de menu"
}

# Exécuter la fonction
hide_vpn_icon

Afficher l'Icône VPN dans la Barre de Menu

#!/bin/bash

# Afficher l'icône VPN dans la barre de menu
show_vpn_icon() {
    echo "=== Ajout de l'Icône VPN à la Barre de Menu ==="
    
    local currentUser
    currentUser=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$currentUser" == "loginwindow" || -z "$currentUser" ]]; then
        echo "❌ Aucune session utilisateur active trouvée"
        return 1
    fi
    
    echo "👤 Utilisateur actuel : $currentUser"
    
    runAsUser() {
        local currentUserID
        currentUserID=$(id -u "$currentUser")
        if [[ "$currentUser" != "loginwindow" ]]; then
            /bin/launchctl asuser "$currentUserID" sudo -u "$currentUser" "$@"
        fi
    }
    
    # Ajouter l'extra de menu VPN
    local vpn_path="/System/Library/CoreServices/Menu Extras/VPN.menu"
    if runAsUser /usr/libexec/PlistBuddy -c "add menuExtras: string '$vpn_path'" "/Users/$currentUser/Library/Preferences/com.apple.systemuiserver.plist" 2>/dev/null; then
        echo "✅ Entrée menu VPN ajoutée"
    else
        echo "⚠️  Entrée menu VPN existe déjà"
    fi
    
    # Redémarrer les services système
    runAsUser /usr/bin/killall cfprefsd 2>/dev/null
    runAsUser /usr/bin/killall SystemUIServer 2>/dev/null
    
    echo "✅ Icône VPN affichée dans la barre de menu"
}

# Exécuter la fonction
show_vpn_icon

Système de Gestion de Barre de Menu d'Entreprise

#!/bin/bash

# Système de Gestion de Barre de Menu d'Entreprise Roundfleet
# Personnalisation d'interface complète, optimisation de l'expérience utilisateur et déploiement de flotte

# Configuration
LOG_FILE="/var/log/roundfleet_menubar.log"
CONFIG_DIR="/etc/roundfleet/interface"
PROFILES_DIR="$CONFIG_DIR/profiles"
BACKUP_DIR="/var/backups/menubar_configs"
REPORTS_DIR="$CONFIG_DIR/reports"

# Extras de menu disponibles
declare -A MENU_EXTRAS=(
    ["vpn"]="/System/Library/CoreServices/Menu Extras/VPN.menu"
    ["wifi"]="/System/Library/CoreServices/Menu Extras/AirPort.menu"
    ["bluetooth"]="/System/Library/CoreServices/Menu Extras/Bluetooth.menu"
    ["volume"]="/System/Library/CoreServices/Menu Extras/Volume.menu"
    ["batterie"]="/System/Library/CoreServices/Menu Extras/Battery.menu"
    ["horloge"]="/System/Library/CoreServices/Menu Extras/Clock.menu"
    ["ecrans"]="/System/Library/CoreServices/Menu Extras/Displays.menu"
    ["timemachine"]="/System/Library/CoreServices/Menu Extras/TimeMachine.menu"
    ["saisie-texte"]="/System/Library/CoreServices/Menu Extras/TextInput.menu"
    ["script"]="/System/Library/CoreServices/Menu Extras/Script Menu.menu"
)

# Configurations de profils
declare -A MENU_PROFILES=(
    ["minimal"]="horloge,batterie,wifi"
    ["standard"]="horloge,batterie,wifi,volume,bluetooth"
    ["complet"]="horloge,batterie,wifi,volume,bluetooth,ecrans,vpn"
    ["entreprise"]="horloge,batterie,wifi,vpn,timemachine"
    ["education"]="horloge,batterie,wifi,volume,saisie-texte"
    ["kiosque"]="horloge,batterie"
    ["developpeur"]="horloge,batterie,wifi,volume,bluetooth,ecrans,script"
    ["securise"]="horloge,batterie,wifi"
)

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

# Configurer les répertoires
setup_directories() {
    for dir in "$CONFIG_DIR" "$PROFILES_DIR" "$BACKUP_DIR" "$REPORTS_DIR"; do
        if [[ ! -d "$dir" ]]; then
            mkdir -p "$dir"
            log_action "Répertoire créé : $dir"
        fi
    done
}

# Obtenir l'utilisateur actuel
get_current_user() {
    local user
    user=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
    
    if [[ "$user" == "loginwindow" || -z "$user" ]]; then
        return 1
    fi
    
    echo "$user"
    return 0
}

# Exécuter une commande en tant qu'utilisateur actuel
run_as_user() {
    local user="$1"
    shift
    
    local userID
    userID=$(id -u "$user" 2>/dev/null) || return 1
    
    /bin/launchctl asuser "$userID" sudo -u "$user" "$@"
}

# Obtenir la configuration actuelle de la barre de menu
get_current_menubar_config() {
    local user="$1"
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    
    if [[ ! -f "$plist_path" ]]; then
        echo "[]"
        return 1
    fi
    
    # Extraire les extras de menu actuels
    local menu_extras
    menu_extras=$(run_as_user "$user" /usr/libexec/PlistBuddy -c "print menuExtras:" "$plist_path" 2>/dev/null | grep -E "\.menu$" | sed 's/^[ ]*//' || echo "")
    
    if [[ -z "$menu_extras" ]]; then
        echo "[]"
    else
        echo "$menu_extras" | jq -R -s 'split("\n") | map(select(length > 0))'
    fi
}

# Appliquer un profil de barre de menu
apply_menubar_profile() {
    local profile_name="$1"
    local target_user="$2"
    
    log_action "Application du profil de barre de menu : $profile_name"
    
    # Obtenir la configuration du profil
    local profile_config="${MENU_PROFILES[$profile_name]}"
    if [[ -z "$profile_config" ]]; then
        log_action "❌ Profil inconnu : $profile_name"
        return 1
    fi
    
    # Obtenir les utilisateurs cibles
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Obtenir tous les utilisateurs avec UID >= 500
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Appliquer le profil à chaque utilisateur
    for user in "${users[@]}"; do
        log_action "Configuration de la barre de menu pour l'utilisateur : $user"
        
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Sauvegarder la configuration actuelle
        backup_user_menubar_config "$user"
        
        # Effacer les extras de menu existants
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Ajouter les éléments du profil
        IFS=',' read -ra ITEMS <<< "$profile_config"
        local index=0
        
        for item in "${ITEMS[@]}"; do
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                log_action "Élément de menu ajouté : $item pour l'utilisateur : $user"
                ((index++))
            else
                log_action "⚠️  Élément de menu non trouvé : $item"
            fi
        done
        
        # Redémarrer les services UI
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Profil '$profile_name' appliqué à l'utilisateur : $user"
    done
    
    return 0
}

# Sauvegarder la configuration de barre de menu utilisateur
backup_user_menubar_config() {
    local user="$1"
    local timestamp
    timestamp=$(date '+%Y%m%d_%H%M%S')
    
    local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
    local backup_file="$BACKUP_DIR/menubar_${user}_${timestamp}.plist"
    
    if [[ -f "$plist_path" ]]; then
        cp "$plist_path" "$backup_file" 2>/dev/null
        log_action "Configuration barre de menu sauvegardée pour $user : $backup_file"
        echo "$backup_file"
    fi
}

# Configuration de barre de menu personnalisée
configure_custom_menubar() {
    local items_string="$1"
    local target_user="$2"
    
    log_action "Application de la configuration de barre de menu personnalisée : $items_string"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        while IFS= read -r user; do
            users+=("$user")
        done < <(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}')
    fi
    
    # Analyser les éléments
    IFS=',' read -ra ITEMS <<< "$items_string"
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Sauvegarder et effacer
        backup_user_menubar_config "$user"
        run_as_user "$user" /usr/libexec/PlistBuddy -c "delete menuExtras:" "$plist_path" 2>/dev/null || true
        run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras: array" "$plist_path" 2>/dev/null
        
        # Ajouter les éléments personnalisés
        local index=0
        for item in "${ITEMS[@]}"; do
            # Supprimer les espaces
            item=$(echo "$item" | sed 's/^[ \t]*//;s/[ \t]*$//')
            
            local menu_path="${MENU_EXTRAS[$item]}"
            if [[ -n "$menu_path" && -f "$menu_path" ]]; then
                run_as_user "$user" /usr/libexec/PlistBuddy -c "add menuExtras:$index string '$menu_path'" "$plist_path" 2>/dev/null
                ((index++))
            fi
        done
        
        # Appliquer les changements
        run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
        run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
        
        log_action "✅ Configuration personnalisée appliquée à l'utilisateur : $user"
    done
}

# Générer un rapport d'audit de barre de menu
generate_menubar_audit() {
    log_action "Génération du rapport d'audit de barre de menu"
    
    local report_file="$REPORTS_DIR/menubar_audit_$(date '+%Y%m%d_%H%M%S').json"
    
    cat > "$report_file" << EOF
{
    "audit_metadata": {
        "timestamp": "$(date -Iseconds)",
        "hostname": "$(hostname)",
        "os_version": "$(sw_vers -productVersion)",
        "generator": "Roundfleet Menu Bar Manager"
    },
    "user_configurations": [
EOF

    local first=true
    local total_users=0
    
    # Auditer chaque utilisateur
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        total_users=$((total_users + 1))
        
        if [[ "$first" == true ]]; then
            first=false
        else
            echo "," >> "$report_file"
        fi
        
        local current_config
        current_config=$(get_current_menubar_config "$user")
        
        local last_login
        last_login=$(last -1 "$user" | head -1 | awk '{print $4, $5, $6, $7}' || echo 'Jamais')
        
        cat >> "$report_file" << EOF
        {
            "username": "$user",
            "current_menu_items": $current_config,
            "item_count": $(echo "$current_config" | jq 'length'),
            "last_login": "$last_login",
            "config_file_exists": $([ -f "/Users/$user/Library/Preferences/com.apple.systemuiserver.plist" ] && echo "true" || echo "false")
        }
EOF
        
        log_action "Utilisateur audité : $user"
    done
    
    cat >> "$report_file" << EOF
    ],
    "summary": {
        "total_users": $total_users,
        "available_menu_items": $(echo "${!MENU_EXTRAS[@]}" | tr ' ' '\n' | jq -R . | jq -s .),
        "available_profiles": $(echo "${!MENU_PROFILES[@]}" | tr ' ' '\n' | jq -R . | jq -s .)
    }
}
EOF

    log_action "✅ Audit de barre de menu terminé : $report_file"
    echo "$report_file"
}

# Restaurer la configuration de barre de menu depuis une sauvegarde
restore_menubar_config() {
    local backup_file="$1"
    local target_user="$2"
    
    if [[ ! -f "$backup_file" ]]; then
        log_action "❌ Fichier de sauvegarde non trouvé : $backup_file"
        return 1
    fi
    
    log_action "Restauration de la configuration de barre de menu depuis : $backup_file"
    
    local users=()
    if [[ -n "$target_user" ]]; then
        users=("$target_user")
    else
        # Extraire le nom d'utilisateur du nom de fichier de sauvegarde
        local extracted_user
        extracted_user=$(basename "$backup_file" | sed 's/menubar_\(.*\)_[0-9]*_[0-9]*.plist/\1/')
        if [[ -n "$extracted_user" ]]; then
            users=("$extracted_user")
        fi
    fi
    
    for user in "${users[@]}"; do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        # Créer une sauvegarde actuelle avant la restauration
        backup_user_menubar_config "$user"
        
        # Restaurer la configuration
        if cp "$backup_file" "$plist_path" 2>/dev/null; then
            chown "$user:staff" "$plist_path" 2>/dev/null
            
            # Appliquer les changements
            run_as_user "$user" /usr/bin/killall cfprefsd 2>/dev/null
            run_as_user "$user" /usr/bin/killall SystemUIServer 2>/dev/null
            
            log_action "✅ Configuration restaurée pour l'utilisateur : $user"
        else
            log_action "❌ Échec de la restauration de configuration pour l'utilisateur : $user"
            return 1
        fi
    done
    
    return 0
}

# Surveiller les changements de barre de menu
monitor_menubar_changes() {
    local duration="${1:-3600}"  # 1 heure par défaut
    local check_interval="${2:-60}"  # 1 minute par défaut
    
    log_action "Démarrage de la surveillance de barre de menu pour ${duration} secondes"
    
    local monitoring_report="$REPORTS_DIR/menubar_monitoring_$(date '+%Y%m%d_%H%M%S').json"
    local baseline_file="/tmp/menubar_baseline.json"
    
    # Créer une ligne de base
    generate_menubar_audit > "$baseline_file"
    
    cat > "$monitoring_report" << EOF
{
    "monitoring_metadata": {
        "start_time": "$(date -Iseconds)",
        "duration_seconds": $duration,
        "check_interval_seconds": $check_interval,
        "hostname": "$(hostname)"
    },
    "changes_detected": [
EOF

    local start_time end_time
    start_time=$(date +%s)
    end_time=$((start_time + duration))
    
    local first=true
    while [[ $(date +%s) -lt $end_time ]]; do
        sleep "$check_interval"
        
        # Vérifier les changements
        local current_state="/tmp/menubar_current.json"
        generate_menubar_audit > "$current_state"
        
        if ! diff "$baseline_file" "$current_state" >/dev/null 2>&1; then
            if [[ "$first" == true ]]; then
                first=false
            else
                echo "," >> "$monitoring_report"
            fi
            
            cat >> "$monitoring_report" << EOF
        {
            "timestamp": "$(date -Iseconds)",
            "change_type": "menu_bar_configuration_change",
            "details": "Changements détectés dans la configuration de barre de menu"
        }
EOF
            
            log_action "⚠️  Changements de configuration de barre de menu détectés"
            cp "$current_state" "$baseline_file"
        fi
        
        rm -f "$current_state"
    done
    
    cat >> "$monitoring_report" << EOF
    ],
    "end_time": "$(date -Iseconds)"
}
EOF

    log_action "✅ Surveillance de barre de menu terminée : $monitoring_report"
    rm -f "$baseline_file"
    echo "$monitoring_report"
}

# Fonction d'exécution principale
main() {
    local action="${1:-audit}"
    local parameter="$2"
    local additional_param="$3"
    
    log_action "=== Démarrage de la Gestion de Barre de Menu Roundfleet ==="
    log_action "Action : $action"
    log_action "Paramètre : ${parameter:-N/A}"
    
    setup_directories
    
    case "$action" in
        "profile")
            if [[ -z "$parameter" ]]; then
                echo "Profils de barre de menu disponibles :"
                for profile in "${!MENU_PROFILES[@]}"; do
                    echo "  - $profile : ${MENU_PROFILES[$profile]}"
                done
                echo ""
                echo "Usage : $0 profile <nom_profil> [nom_utilisateur]"
                exit 1
            fi
            apply_menubar_profile "$parameter" "$additional_param"
            ;;
        "custom")
            if [[ -z "$parameter" ]]; then
                echo "Éléments de menu disponibles :"
                for item in "${!MENU_EXTRAS[@]}"; do
                    echo "  - $item"
                done
                echo ""
                echo "Usage : $0 custom <item1,item2,item3> [nom_utilisateur]"
                echo "Exemple : $0 custom horloge,batterie,wifi,vpn john.doe"
                exit 1
            fi
            configure_custom_menubar "$parameter" "$additional_param"
            ;;
        "audit")
            generate_menubar_audit
            ;;
        "monitor")
            monitor_menubar_changes "$parameter" "$additional_param"
            ;;
        "restore")
            if [[ -z "$parameter" ]]; then
                echo "Usage : $0 restore <fichier_sauvegarde> [nom_utilisateur]"
                echo "Sauvegardes disponibles :"
                ls -la "$BACKUP_DIR"/*.plist 2>/dev/null || echo "Aucune sauvegarde trouvée"
                exit 1
            fi
            restore_menubar_config "$parameter" "$additional_param"
            ;;
        "hide-vpn")
            local user
            if user=$(get_current_user); then
                hide_vpn_icon
            else
                echo "❌ Aucune session utilisateur active"
                exit 1
            fi
            ;;
        "show-vpn")
            local user
            if user=$(get_current_user); then
                show_vpn_icon
            else
                echo "❌ Aucune session utilisateur active"
                exit 1
            fi
            ;;
        *)
            echo "Usage : $0 {profile|custom|audit|monitor|restore|hide-vpn|show-vpn}"
            echo "  profile     - Appliquer un profil de barre de menu prédéfini"
            echo "  custom      - Appliquer une configuration de barre de menu personnalisée"
            echo "  audit       - Générer un rapport d'audit de barre de menu"
            echo "  monitor     - Surveiller les changements de barre de menu dans le temps"
            echo "  restore     - Restaurer depuis une sauvegarde"
            echo "  hide-vpn    - Masquer l'icône VPN de la barre de menu"
            echo "  show-vpn    - Afficher l'icône VPN dans la barre de menu"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion de barre de menu terminée ==="
}

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

Exemples de Profils de Barre de Menu

Configuration de Profil d'Entreprise

#!/bin/bash

# Appliquer le profil de barre de menu d'entreprise sur tous les appareils
deploy_corporate_profile() {
    echo "=== Déploiement de Barre de Menu d'Entreprise ==="
    
    # Profil d'entreprise : horloge, batterie, wifi, vpn, timemachine
    local corporate_items="horloge,batterie,wifi,vpn,timemachine"
    
    # Obtenir tous les utilisateurs
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        echo "Configuration du profil d'entreprise pour : $user"
        
        # Appliquer la configuration
        configure_custom_menubar "$corporate_items" "$user"
        
        # Vérifier l'application
        sleep 2
        local current_config
        current_config=$(get_current_menubar_config "$user")
        echo "Configuration appliquée : $current_config"
    done
    
    echo "✅ Profil d'entreprise déployé pour tous les utilisateurs"
}

Configuration Mode Kiosque

#!/bin/bash

# Barre de menu minimale pour les environnements kiosque
setup_kiosk_menubar() {
    echo "=== Configuration de Barre de Menu Kiosque ==="
    
    # Éléments minimaux : horloge et batterie seulement
    local kiosk_items="horloge,batterie"
    
    local target_user="$1"
    if [[ -z "$target_user" ]]; then
        echo "Usage : setup_kiosk_menubar <nom_utilisateur>"
        return 1
    fi
    
    configure_custom_menubar "$kiosk_items" "$target_user"
    
    echo "✅ Barre de menu kiosque configurée pour : $target_user"
}

Fonctionnalités Avancées de Barre de Menu

Commutation Dynamique de Profils

#!/bin/bash

# Basculer entre différents profils selon les conditions
smart_profile_switching() {
    local user="$1"
    
    echo "=== Commutation Intelligente de Profils ==="
    
    # Détecter l'environnement
    if pgrep -f "VPN" >/dev/null; then
        echo "VPN détecté - application du profil d'entreprise"
        apply_menubar_profile "entreprise" "$user"
    elif [[ $(pmset -g batt | grep -c "Battery") -gt 0 ]]; then
        echo "Alimentation batterie détectée - application du profil minimal"
        apply_menubar_profile "minimal" "$user"
    else
        echo "Environnement standard - application du profil complet"
        apply_menubar_profile "complet" "$user"
    fi
}

Vérification de Santé de Barre de Menu

#!/bin/bash

# Vérifier l'intégrité de la configuration de barre de menu
menubar_health_check() {
    echo "=== Vérification de Santé de Barre de Menu ==="
    
    local issues_found=0
    
    for user in $(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}'); do
        local plist_path="/Users/$user/Library/Preferences/com.apple.systemuiserver.plist"
        
        if [[ ! -f "$plist_path" ]]; then
            echo "⚠️  Fichier de configuration manquant pour l'utilisateur : $user"
            issues_found=$((issues_found + 1))
            continue
        fi
        
        # Vérifier si SystemUIServer fonctionne
        if ! pgrep -u "$(id -u "$user")" SystemUIServer >/dev/null; then
            echo "⚠️  SystemUIServer ne fonctionne pas pour l'utilisateur : $user"
            issues_found=$((issues_found + 1))
        fi
        
        # Valider le format plist
        if ! plutil -lint "$plist_path" >/dev/null 2>&1; then
            echo "❌ Fichier plist corrompu pour l'utilisateur : $user"
            issues_found=$((issues_found + 1))
        fi
    done
    
    if [[ $issues_found -eq 0 ]]; then
        echo "✅ Toutes les configurations de barre de menu sont saines"
    else
        echo "⚠️  Trouvé $issues_found problèmes nécessitant une attention"
    fi
    
    return $issues_found
}

Meilleures Pratiques

🎯 Optimisation de l'Expérience Utilisateur

  • Image de marque cohérente sur tous les appareils avec des dispositions de barre de menu standardisées
  • Configurations basées sur les profils pour différents rôles utilisateur et environnements
  • Configurations kiosque minimales pour les appareils publics ou à usage restreint
  • Commutation dynamique basée sur l'état d'alimentation ou les conditions réseau

🔧 Gestion d'Entreprise

  • Déploiement centralisé des configurations de barre de menu sur les flottes d'appareils
  • Capacités de sauvegarde et restauration pour la gestion de configuration
  • Rapports d'audit pour la vérification de conformité et de standardisation
  • Surveillance des changements avec détection automatisée et alertes

🔐 Considérations de Sécurité

  • Supprimer les indicateurs sensibles des appareils publics
  • Masquer le statut VPN dans les environnements où les informations réseau doivent être privées
  • Standardiser les affichages d'entreprise pour éviter les fuites d'information
  • Surveiller les changements non autorisés des configurations de barre de menu

📊 Surveillance et Maintenance

  • Vérifications de santé régulières pour assurer l'intégrité de la configuration
  • Application automatisée de profils pour maintenir la cohérence
  • Détection de changements avec capacités de retour en arrière
  • Collection de commentaires d'expérience utilisateur et optimisation

Notes Importantes

  • macOS 12+ requis pour une compatibilité optimale avec les extras de menu modernes
  • Session utilisateur active requise pour les modifications de barre de menu
  • Redémarrage système peut être nécessaire pour que certains changements prennent pleinement effet
  • Tester minutieusement avant de déployer en environnements de production
  • Sauvegarder les configurations avant d'apporter des changements pour permettre un retour facile

Gérer les panneaux de réglages système sur macOS

Contrôlez quels panneaux de réglages système les utilisateurs peuvent accéder sur macOS Ventura et versions ultérieures. Ce tutoriel montre comment désactiver ou masquer des panneaux de préférences spécifiques pour maintenir la sécurité et empêcher les modifications de configuration non désirées sur votre Roundfleet.

Comprendre Réglages Système vs Préférences Système

macOS Ventura (13.0+) a remplacé "Préférences Système" par "Réglages Système". L'approche de gestion diffère entre les versions :

  • macOS 13.0+ : Utilisez DisabledSystemSettings et des identifiants de bundle se terminant par .extension
  • macOS 12.x et antérieures : Utilisez DisabledPreferencePanes avec des identifiants de bundle différents

Désactiver les panneaux de réglages système

Script de désactivation de base

#!/bin/bash

# Désactiver un panneau de réglages système spécifique
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "com.apple.Battery-Settings.extension"

echo "Panneau de réglages système désactivé avec succès"

Désactiver plusieurs panneaux

#!/bin/bash

# Désactiver plusieurs panneaux de réglages système
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings" \
    "com.apple.Network-Settings.extension" \
    "com.apple.Battery-Settings.extension"

echo "Plusieurs panneaux de réglages système désactivés"

Identifiants de bundle des réglages système

Nom du panneauIdentifiant de bundle
Accessibilitécom.apple.Accessibility-Settings.extension
AirDrop et Handoffcom.apple.AirDrop-Handoff-Settings.extension
Identifiant Applecom.apple.systempreferences.AppleIDSettings
Batteriecom.apple.Battery-Settings.extension
Bluetoothcom.apple.BluetoothSettings
Centre de contrôlecom.apple.ControlCenter-Settings.extension
Date et heurecom.apple.Date-Time-Settings.extension
Bureau et Dockcom.apple.Desktop-Settings.extension
Moniteurscom.apple.Displays-Settings.extension
Extensionscom.apple.ExtensionsPreferences
Concentrationcom.apple.Focus-Settings.extension
Game Centercom.apple.Game-Center-Settings.extension
Comptes Internetcom.apple.Internet-Accounts-Settings.extension
Claviercom.apple.Keyboard-Settings.extension
Langue et régioncom.apple.Localization-Settings.extension
Écran de verrouillagecom.apple.Lock-Screen-Settings.extension
Ouverture de sessioncom.apple.LoginItems-Settings.extension
Réseaucom.apple.Network-Settings.extension
Notificationscom.apple.Notifications-Settings.extension
Mots de passecom.apple.Passwords-Settings.extension
Imprimantes et scannerscom.apple.Print-Scan-Settings.extension
Temps d'écrancom.apple.Screen-Time-Settings.extension
Économiseur d'écrancom.apple.ScreenSaver-Settings.extension
Partagecom.apple.Sharing-Settings.extension
Siri et Spotlightcom.apple.Siri-Settings.extension
Mise à jour logiciellecom.apple.Software-Update-Settings.extension
Soncom.apple.Sound-Settings.extension
Disque de démarragecom.apple.Startup-Disk-Settings.extension
Stockagecom.apple.settings.Storage
Time Machinecom.apple.Time-Machine-Settings.extension
Touch ID et mot de passecom.apple.Touch-ID-Settings.extension
Trackpadcom.apple.Trackpad-Settings.extension
Transfert ou réinitialisationcom.apple.Transfer-Reset-Settings.extension
Utilisateurs et groupescom.apple.Users-Groups-Settings.extension
Portefeuille et Apple Paycom.apple.WalletSettingsExtension
Fond d'écrancom.apple.Wallpaper-Settings.extension
Wi-Ficom.apple.wifi-settings-extension

Ouvrir les panneaux de réglages système à distance

Ouvrir un panneau spécifique

#!/bin/bash

# Ouvrir le panneau des réglages réseau
open "x-apple.systempreferences:com.apple.Network-Settings.extension"

echo "Panneau des réglages réseau ouvert"

Ouverture conditionnelle de panneau

#!/bin/bash

PANEL_ID="com.apple.Battery-Settings.extension"

# Vérifier si le panneau n'est pas désactivé avant de l'ouvrir
if ! defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "$PANEL_ID"; then
    open "x-apple.systempreferences:$PANEL_ID"
    echo "Panneau des réglages de batterie ouvert"
else
    echo "Panneau des réglages de batterie désactivé"
fi

Réactiver les panneaux désactivés

Réactiver tous les panneaux

#!/bin/bash

# Supprimer toutes les restrictions des réglages système
defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

echo "Tous les panneaux de réglages système réactivés"

Réactiver des panneaux spécifiques

#!/bin/bash

# Obtenir les panneaux actuellement désactivés
CURRENT_DISABLED=$(defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null)

# Supprimer un panneau spécifique de la liste des désactivés (nécessite une logique personnalisée)
# Cet exemple montre le concept - implémentez selon vos besoins
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array \
    "com.apple.BluetoothSettings"
    # Ajoutez les autres panneaux que vous voulez garder désactivés

echo "Panneaux de réglages système spécifiques réactivés"

Script de gestion d'entreprise

#!/bin/bash

# Gestion des réglages système d'entreprise
# Restreint l'accès aux panneaux de configuration sensibles

RESTRICTED_PANELS=(
    "com.apple.Network-Settings.extension"
    "com.apple.BluetoothSettings"
    "com.apple.Security-Privacy-Settings.extension"
    "com.apple.Software-Update-Settings.extension"
    "com.apple.Users-Groups-Settings.extension"
)

# Appliquer les restrictions
defaults write "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings -array "${RESTRICTED_PANELS[@]}"

# Vérifier les restrictions
echo "Panneaux de réglages système désactivés :"
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null || echo "Aucun panneau actuellement désactivé"

# Enregistrer l'action
logger "Roundfleet: Panneaux de réglages système restreints le $(date)"

Dépannage

Vérifier les restrictions actuelles

# Voir les panneaux actuellement désactivés
defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings

# Vérifier si un panneau spécifique est désactivé
if defaults read "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings 2>/dev/null | grep -q "com.apple.Battery-Settings.extension"; then
    echo "Le panneau batterie est désactivé"
else
    echo "Le panneau batterie est accessible"
fi

Supprimer toutes les restrictions

# Réinitialisation d'urgence - réactiver tous les panneaux
sudo defaults delete "/Library/Preferences/com.apple.systempreferences" DisabledSystemSettings
sudo killall cfprefsd

Cas d'utilisation courants

ScénarioPanneaux recommandés à désactiver
Postes partagésUtilisateurs et groupes, Mise à jour logicielle, Réseau
Appareils BYODIdentifiant Apple, Transfert ou réinitialisation, Utilisateurs et groupes
Mode kiosqueTous sauf les panneaux essentiels au fonctionnement
Laboratoires éducatifsRéseau, Mise à jour logicielle, Touch ID et mot de passe
Sécurité d'entrepriseMise à jour logicielle, Transfert ou réinitialisation, Partage

Notes importantes

  • Compatibilité macOS : Ces scripts fonctionnent uniquement sur macOS 13.0 (Ventura) et versions ultérieures
  • Expérience utilisateur : Les panneaux désactivés apparaissent grisés mais restent visibles
  • Redémarrage système : Les modifications prennent effet immédiatement sans redémarrage
  • Persistance : Les paramètres persistent entre les sessions utilisateur et les redémarrages système

Pour les appareils fonctionnant sous macOS 12.x et antérieures, utilisez l'approche de gestion des préférences système héritée avec des identifiants de bundle différents.

Gérer les processus en cours d'exécution sur macOS

Surveillez et contrôlez les processus en cours d'exécution sur vos appareils Roundfleet en utilisant des outils en ligne de commande. Ce tutoriel couvre la surveillance du CPU, l'analyse de la mémoire, la liste des processus et la terminaison de processus pour une gestion système efficace.

Comprendre la gestion des processus macOS

macOS fournit plusieurs outils en ligne de commande pour la gestion des processus :

  • top - Affichage en temps réel des processus en cours et de l'utilisation système
  • ps - Instantané des processus actuels
  • kill - Terminer des processus par PID
  • Moniteur d'activité - Équivalent GUI pour la surveillance visuelle

Afficher l'utilisation du CPU

Utilisation basique du CPU

#!/bin/bash

# Afficher l'utilisation actuelle du CPU
top -l 1 -s 0 | grep "CPU usage"

echo "Utilisation du CPU récupérée avec succès"

Analyse détaillée du CPU

#!/bin/bash

# Obtenir des informations complètes sur le CPU
echo "=== Analyse d'utilisation du CPU ==="
echo "Utilisation actuelle du CPU :"
top -l 1 -s 0 | grep "CPU usage"

echo -e "\nProcessus consommant le plus de CPU :"
top -l 1 -s 0 | head -20 | tail -10

echo -e "\nMoyenne de charge :"
uptime

Afficher l'état de la mémoire

Informations basiques de la mémoire

#!/bin/bash

# Afficher l'utilisation de la mémoire
top -l 1 -s 0 | grep PhysMem

echo "État de la mémoire récupéré avec succès"

Analyse complète de la mémoire

#!/bin/bash

# Rapport détaillé de la mémoire
echo "=== Analyse de l'état de la mémoire ==="
echo "Utilisation de la mémoire physique :"
top -l 1 -s 0 | grep PhysMem

echo -e "\nStatistiques de la mémoire virtuelle :"
vm_stat

echo -e "\nPression mémoire :"
memory_pressure

Lister les processus en cours d'exécution

Voir tous les processus

#!/bin/bash

# Lister tous les processus en cours d'exécution
ps aux

echo "Liste des processus générée avec succès"

Liste limitée de processus

#!/bin/bash

# Afficher les 10 premiers processus
echo "Top 10 des processus en cours :"
ps aux | head -11

# Afficher un nombre spécifique de processus (remplacer 15 par le nombre désiré)
echo -e "\nTop 15 des processus :"
ps aux | head -16

Vues filtrées des processus

#!/bin/bash

# Afficher seulement les processus utilisateur
echo "Processus utilisateur :"
ps aux | grep -v "^root"

echo -e "\nProcessus système :"
ps aux | grep "^root" | head -10

echo -e "\nProcessus utilisant le plus de CPU :"
ps aux --sort=-%cpu | head -10

echo -e "\nProcessus utilisant le plus de mémoire :"
ps aux --sort=-%mem | head -10

Terminaison de processus

Tuer un processus par PID

#!/bin/bash

# Tuer un processus spécifique (remplacer PID par l'ID de processus réel)
PID="1234"

if kill -9 "$PID" 2>/dev/null; then
    echo "Processus $PID terminé avec succès"
else
    echo "Échec de la terminaison du processus $PID ou processus introuvable"
fi

Tuer un processus par nom

#!/bin/bash

# Tuer un processus par nom d'application
APP_NAME="Safari"

if pkill -f "$APP_NAME"; then
    echo "Processus $APP_NAME terminés avec succès"
else
    echo "Aucun processus $APP_NAME trouvé ou échec de la terminaison"
fi

Terminaison sécurisée de processus

#!/bin/bash

# Terminer gracieusement un processus avec confirmation
terminate_process() {
    local pid="$1"
    local process_name
    
    # Obtenir le nom du processus
    process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
    
    if [[ -z "$process_name" ]]; then
        echo "Processus $pid introuvable"
        return 1
    fi
    
    echo "Processus trouvé : $process_name (PID: $pid)"
    
    # Essayer d'abord une terminaison gracieuse
    if kill -TERM "$pid" 2>/dev/null; then
        echo "Signal de terminaison envoyé à $process_name"
        sleep 3
        
        # Vérifier si le processus existe encore
        if kill -0 "$pid" 2>/dev/null; then
            echo "Processus encore actif, forcer la terminaison..."
            kill -9 "$pid" 2>/dev/null
        fi
        
        echo "Processus $process_name terminé"
        return 0
    else
        echo "Échec de la terminaison du processus $process_name"
        return 1
    fi
}

# Exemple d'utilisation (remplacer par le PID réel)
# terminate_process 1234

Script de gestion de processus d'entreprise

#!/bin/bash

# Outil de gestion des processus Roundfleet
# Surveiller et gérer les processus sur les appareils de la flotte

# Configuration
LOG_FILE="/var/log/roundfleet_processes.log"
ALERT_CPU_THRESHOLD=80
ALERT_MEMORY_THRESHOLD=80

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

# Obtenir les statistiques système
get_system_stats() {
    echo "=== Statistiques système ==="
    
    # Utilisation CPU
    local cpu_info
    cpu_info=$(top -l 1 -s 0 | grep "CPU usage")
    echo "CPU : $cpu_info"
    
    # Utilisation mémoire
    local mem_info
    mem_info=$(top -l 1 -s 0 | grep PhysMem)
    echo "Mémoire : $mem_info"
    
    # Moyenne de charge
    echo "Charge : $(uptime | awk -F'load average:' '{print $2}')"
    
    # Top processus
    echo -e "\nTop 5 des consommateurs CPU :"
    ps aux --sort=-%cpu | head -6 | tail -5
    
    echo -e "\nTop 5 des consommateurs mémoire :"
    ps aux --sort=-%mem | head -6 | tail -5
}

# Vérifier la santé du système
check_system_health() {
    echo "=== Vérification de la santé du système ==="
    
    # Vérifier les processus haute utilisation CPU
    local high_cpu_procs
    high_cpu_procs=$(ps aux | awk -v threshold="$ALERT_CPU_THRESHOLD" '$3 > threshold {print $2, $11, $3"%"}')
    
    if [[ -n "$high_cpu_procs" ]]; then
        echo "⚠️  Processus haute utilisation CPU :"
        echo "$high_cpu_procs"
        log_action "Alerte CPU élevé : $high_cpu_procs"
    fi
    
    # Vérifier les processus haute utilisation mémoire
    local high_mem_procs
    high_mem_procs=$(ps aux | awk -v threshold="$ALERT_MEMORY_THRESHOLD" '$4 > threshold {print $2, $11, $4"%"}')
    
    if [[ -n "$high_mem_procs" ]]; then
        echo "⚠️  Processus haute utilisation mémoire :"
        echo "$high_mem_procs"
        log_action "Alerte mémoire élevée : $high_mem_procs"
    fi
}

# Tuer les processus incontrôlés
kill_runaway_processes() {
    echo "=== Détection de processus incontrôlés ==="
    
    # Trouver les processus utilisant un CPU excessif (>90% pendant >5 minutes)
    local runaway_pids
    runaway_pids=$(ps aux | awk '$3 > 90 {print $2}')
    
    for pid in $runaway_pids; do
        local process_name
        process_name=$(ps -p "$pid" -o comm= 2>/dev/null)
        
        if [[ -n "$process_name" ]]; then
            echo "Processus incontrôlé trouvé : $process_name (PID: $pid)"
            
            # Ignorer les processus système critiques
            if [[ "$process_name" =~ ^(kernel|launchd|WindowServer)$ ]]; then
                echo "Ignorer le processus système critique : $process_name"
                continue
            fi
            
            log_action "Terminaison du processus incontrôlé : $process_name (PID: $pid)"
            kill -TERM "$pid"
        fi
    done
}

# Fonction principale de surveillance
main() {
    log_action "=== Surveillance des processus Roundfleet démarrée ==="
    
    get_system_stats
    echo ""
    check_system_health
    echo ""
    
    # Optionnellement tuer les processus incontrôlés (décommenter pour activer)
    # kill_runaway_processes
    
    log_action "=== Surveillance des processus terminée ==="
}

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

Détails des informations de processus

Lors de l'utilisation de ps aux, chaque colonne fournit des informations spécifiques :

ColonneDescription
USERUtilisateur exécutant le processus (processus système ou utilisateur)
PIDID du processus (identifiant unique)
%CPUPourcentage d'utilisation CPU
%MEMPourcentage d'utilisation mémoire
VSZTaille de la mémoire virtuelle en KB
RSSUtilisation de la mémoire physique en KB
TTTerminal associé au processus
STATÉtat du processus (R=en cours, S=endormi, Z=zombie)
STARTEDDate/heure de démarrage du processus
TIMETemps CPU consommé
COMMANDCommande utilisée pour démarrer le processus

Tâches courantes de gestion de processus

Trouver un processus par nom

# Trouver les processus Safari
ps aux | grep -i safari

# Trouver tous les processus contenant "mail"
ps aux | grep -i mail | grep -v grep

Surveiller un processus en temps réel

# Surveiller un processus spécifique
watch -n 1 'ps aux | grep -i safari'

# Surveiller les ressources système en continu
top -s 1 -n 10

Générer un rapport de processus

#!/bin/bash

# Créer un rapport complet des processus
REPORT_FILE="process_report_$(date +%Y%m%d_%H%M%S).txt"

{
    echo "Rapport de processus Roundfleet"
    echo "Généré : $(date)"
    echo "Nom d'hôte : $(hostname)"
    echo "=========================="
    echo ""
    
    echo "Aperçu système :"
    top -l 1 -s 0 | grep -E "(CPU usage|PhysMem)"
    echo ""
    
    echo "Top 20 processus :"
    ps aux | head -21
    echo ""
    
    echo "Nombre de processus par utilisateur :"
    ps aux | awk '{print $1}' | sort | uniq -c | sort -nr
    
} > "$REPORT_FILE"

echo "Rapport de processus sauvegardé dans : $REPORT_FILE"

Notes importantes

  • Les ID de processus (PID) changent lorsque les processus redémarrent
  • Les processus système nécessitent des privilèges admin pour être terminés
  • Force kill (kill -9) doit être utilisé en dernier recours
  • Surveiller l'utilisation des ressources avant de terminer des processus
  • Tester les scripts sur des appareils individuels avant le déploiement en flotte

Gérer le chiffrement FileVault sur macOS

FileVault offre un chiffrement complet du disque pour les appareils macOS, protégeant les données sensibles même si l'appareil est perdu ou volé. Ce tutoriel montre comment automatiser la gestion de FileVault sur votre Roundfleet en utilisant des scripts en ligne de commande.

Comprendre FileVault

FileVault chiffre l'ensemble du disque de démarrage en utilisant le chiffrement XTS-AES-128 avec une clé de 256 bits. Les avantages clés incluent :

  • Protection des données - Chiffre toutes les données sur le disque de démarrage
  • Conformité - Répond aux exigences de sécurité d'entreprise
  • Performance - Chiffrement accéléré par le matériel sur les Mac modernes
  • Récupération - Plusieurs options de récupération disponibles

Commandes FileVault de base

Vérifier le statut de FileVault

#!/bin/bash

# Vérifier le statut actuel de FileVault
fdesetup status

# Obtenir des informations détaillées sur le chiffrement
diskutil apfs listCryptoUsers /

Activer FileVault

#!/bin/bash

# Commande de base pour activer FileVault
sudo fdesetup enable --user "username" --password "password"

# Activer avec un trousseau spécifique
sudo fdesetup enable --user "username" --password "password" --keychain /Library/Keychains/System.keychain

Désactiver FileVault

#!/bin/bash

# Commande de base pour désactiver FileVault
sudo fdesetup disable --user "username" --password "password"

Script de gestion FileVault d'entreprise

Script complet pour gérer FileVault sur votre Roundfleet :

#!/bin/bash

# Script de gestion FileVault pour Roundfleet
# Compatible avec macOS 10.14+

# Configuration
LOG_FILE="/var/log/filevault_management.log"
KEYCHAIN_PATH="/Library/Keychains/System.keychain"

# Fonction pour journaliser les messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Fonction pour obtenir l'utilisateur actuel
get_current_user() {
    stat -f "%Su" /dev/console
}

# Fonction pour vérifier si l'utilisateur a un token sécurisé
check_secure_token() {
    local username="$1"
    
    if sysadminctl -secureTokenStatus "$username" 2>/dev/null | grep -q "ENABLED"; then
        return 0
    else
        return 1
    fi
}

# Fonction pour vérifier le statut de FileVault
check_filevault_status() {
    local status
    status=$(fdesetup status)
    
    if echo "$status" | grep -q "FileVault is On"; then
        echo "enabled"
    elif echo "$status" | grep -q "FileVault is Off"; then
        echo "disabled"
    elif echo "$status" | grep -q "Encryption in progress"; then
        echo "encrypting"
    elif echo "$status" | grep -q "Decryption in progress"; then
        echo "decrypting"
    else
        echo "unknown"
    fi
}

# Fonction pour obtenir le progrès du chiffrement
get_encryption_progress() {
    fdesetup status | grep -o '[0-9]\+%' | head -1
}

# Fonction pour valider les identifiants utilisateur
validate_user_credentials() {
    local username="$1"
    local password="$2"
    
    # Vérifier si l'utilisateur existe
    if ! id "$username" &>/dev/null; then
        log_message "✗ L'utilisateur n'existe pas : $username"
        return 1
    fi
    
    # Vérifier si l'utilisateur a des privilèges admin
    if ! dsmemberutil checkmembership -U "$username" -G admin &>/dev/null; then
        log_message "✗ L'utilisateur n'est pas un administrateur : $username"
        return 1
    fi
    
    # Vérifier si l'utilisateur a un token sécurisé
    if ! check_secure_token "$username"; then
        log_message "✗ L'utilisateur n'a pas de token sécurisé : $username"
        return 1
    fi
    
    # Vérifier le mot de passe (vérification de base)
    if [[ -z "$password" ]]; then
        log_message "✗ Le mot de passe ne peut pas être vide pour l'utilisateur : $username"
        return 1
    fi
    
    log_message "✓ Identifiants utilisateur validés : $username"
    return 0
}

# Fonction pour activer FileVault
enable_filevault() {
    local username="$1"
    local password="$2"
    local force_enable="$3"
    
    log_message "Début de l'activation de FileVault pour l'utilisateur : $username"
    
    # Vérifier le statut actuel
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "enabled")
            log_message "! FileVault est déjà activé"
            if [[ "$force_enable" != "true" ]]; then
                return 0
            fi
            ;;
        "encrypting")
            log_message "! Le chiffrement FileVault est déjà en cours"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Progrès du chiffrement : ${progress:-Inconnu}"
            return 0
            ;;
        "decrypting")
            log_message "✗ Impossible d'activer FileVault pendant qu'un déchiffrement est en cours"
            return 1
            ;;
    esac
    
    # Valider les identifiants utilisateur
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Activer FileVault
    log_message "Activation de FileVault..."
    
    if fdesetup enable -user "$username" -password "$password" -keychain "$KEYCHAIN_PATH" 2>/dev/null; then
        log_message "✓ Commande d'activation de FileVault exécutée avec succès"
        
        # Attendre un moment et vérifier le statut
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "enabled")
                log_message "✓ FileVault est maintenant activé"
                ;;
            "encrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ Chiffrement FileVault démarré (${progress:-0%})"
                ;;
            *)
                log_message "! Statut FileVault incertain : $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Échec de l'activation de FileVault"
        return 1
    fi
}

# Fonction pour désactiver FileVault
disable_filevault() {
    local username="$1"
    local password="$2"
    local force_disable="$3"
    
    log_message "Début de la désactivation de FileVault pour l'utilisateur : $username"
    
    # Vérifier le statut actuel
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "disabled")
            log_message "! FileVault est déjà désactivé"
            if [[ "$force_disable" != "true" ]]; then
                return 0
            fi
            ;;
        "decrypting")
            log_message "! Le déchiffrement FileVault est déjà en cours"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Progrès du déchiffrement : ${progress:-Inconnu}"
            return 0
            ;;
        "encrypting")
            log_message "✗ Impossible de désactiver FileVault pendant qu'un chiffrement est en cours"
            return 1
            ;;
    esac
    
    # Valider les identifiants utilisateur
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Désactiver FileVault
    log_message "Désactivation de FileVault..."
    
    if fdesetup disable -user "$username" -password "$password" 2>/dev/null; then
        log_message "✓ Commande de désactivation de FileVault exécutée avec succès"
        
        # Attendre un moment et vérifier le statut
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "disabled")
                log_message "✓ FileVault est maintenant désactivé"
                ;;
            "decrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ Déchiffrement FileVault démarré (${progress:-0%})"
                ;;
            *)
                log_message "! Statut FileVault incertain : $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Échec de la désactivation de FileVault"
        return 1
    fi
}

# Fonction pour obtenir les informations système
get_system_info() {
    log_message "=== Informations système ==="
    log_message "Nom d'hôte : $(hostname)"
    log_message "Version macOS : $(sw_vers -productVersion)"
    log_message "Utilisateur actuel : $(get_current_user)"
    log_message "Statut FileVault : $(check_filevault_status)"
    
    # Obtenir les utilisateurs FileVault
    local fv_users
    fv_users=$(fdesetup list 2>/dev/null)
    if [[ -n "$fv_users" ]]; then
        log_message "Utilisateurs avec FileVault activé :"
        echo "$fv_users" | while read -r line; do
            log_message "  $line"
        done
    fi
}

# Fonction pour afficher l'usage
usage() {
    echo "Usage : $0 {enable|disable|status} [options]"
    echo ""
    echo "Commandes :"
    echo "  enable    Activer FileVault"
    echo "  disable   Désactiver FileVault"
    echo "  status    Vérifier le statut de FileVault"
    echo ""
    echo "Options :"
    echo "  -u, --user USERNAME      Spécifier le nom d'utilisateur"
    echo "  -p, --password PASSWORD  Spécifier le mot de passe"
    echo "  -f, --force             Forcer l'opération même si déjà dans l'état désiré"
    echo "  -h, --help              Afficher ce message d'aide"
    echo ""
    echo "Exemples :"
    echo "  $0 enable -u admin -p password123"
    echo "  $0 disable -u admin -p password123 -f"
    echo "  $0 status"
}

# Fonction principale
main() {
    local command="$1"
    local username=""
    local password=""
    local force="false"
    
    # Analyser les arguments
    shift
    while [[ $# -gt 0 ]]; do
        case $1 in
            -u|--user)
                username="$2"
                shift 2
                ;;
            -p|--password)
                password="$2"
                shift 2
                ;;
            -f|--force)
                force="true"
                shift
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Option inconnue : $1"
                usage
                exit 1
                ;;
        esac
    done
    
    # Exécuter la commande
    case "$command" in
        "enable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Erreur : Nom d'utilisateur et mot de passe requis pour la commande enable"
                usage
                exit 1
            fi
            
            log_message "=== Début de l'opération d'activation de FileVault ==="
            get_system_info
            
            if enable_filevault "$username" "$password" "$force"; then
                log_message "=== Opération d'activation de FileVault terminée avec succès ==="
                exit 0
            else
                log_message "=== Échec de l'opération d'activation de FileVault ==="
                exit 1
            fi
            ;;
        "disable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Erreur : Nom d'utilisateur et mot de passe requis pour la commande disable"
                usage
                exit 1
            fi
            
            log_message "=== Début de l'opération de désactivation de FileVault ==="
            get_system_info
            
            if disable_filevault "$username" "$password" "$force"; then
                log_message "=== Opération de désactivation de FileVault terminée avec succès ==="
                exit 0
            else
                log_message "=== Échec de l'opération de désactivation de FileVault ==="
                exit 1
            fi
            ;;
        "status")
            get_system_info
            exit 0
            ;;
        *)
            echo "Erreur : Commande invalide : $command"
            usage
            exit 1
            ;;
    esac
}

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

Scripts FileVault rapides

Script d'activation simple

#!/bin/bash

USERNAME="admin"
PASSWORD="votre_mot_de_passe_ici"

if fdesetup enable -user "$USERNAME" -password "$PASSWORD"; then
    echo "FileVault activé avec succès"
else
    echo "Échec de l'activation de FileVault"
    exit 1
fi

Vérification simple du statut

#!/bin/bash

STATUS=$(fdesetup status)
echo "Statut FileVault : $STATUS"

if echo "$STATUS" | grep -q "FileVault is On"; then
    echo "✓ FileVault est activé"
    exit 0
elif echo "$STATUS" | grep -q "FileVault is Off"; then
    echo "✗ FileVault est désactivé"
    exit 1
else
    echo "! Statut FileVault incertain"
    exit 2
fi

Gestion des clés de récupération

Générer une clé de récupération personnelle

#!/bin/bash

# Activer FileVault avec clé de récupération personnelle
sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -outputplist > /tmp/filevault_key.plist

# Extraire la clé de récupération
RECOVERY_KEY=$(grep -A1 "RecoveryKey" /tmp/filevault_key.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>.*/\1/')

echo "Clé de récupération : $RECOVERY_KEY"

# Stocker la clé de récupération en sécurité
echo "$RECOVERY_KEY" | sudo tee /var/root/filevault_recovery_key.txt
sudo chmod 600 /var/root/filevault_recovery_key.txt

# Nettoyer
rm -f /tmp/filevault_key.plist

Activer la clé de récupération institutionnelle

#!/bin/bash

# Créer une clé de récupération institutionnelle
CERT_PATH="/path/to/institutional_certificate.cer"

if [[ -f "$CERT_PATH" ]]; then
    sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -certificate "$CERT_PATH"
    echo "FileVault activé avec clé de récupération institutionnelle"
else
    echo "Certificat institutionnel non trouvé : $CERT_PATH"
    exit 1
fi

Dépannage des problèmes courants

Corriger les problèmes de token sécurisé

#!/bin/bash

USERNAME="admin"

# Accorder un token sécurisé à l'utilisateur
sudo sysadminctl -secureTokenOn "$USERNAME" -password -

# Vérifier le token sécurisé
if sysadminctl -secureTokenStatus "$USERNAME" | grep -q "ENABLED"; then
    echo "✓ Token sécurisé activé pour $USERNAME"
else
    echo "✗ Échec de l'activation du token sécurisé pour $USERNAME"
fi

Gérer l'erreur de mot de passe vide

#!/bin/bash

USERNAME="admin"

# Vérifier si l'utilisateur a un mot de passe défini
if dscl . -read "/Users/$USERNAME" AuthenticationAuthority | grep -q "No such key"; then
    echo "L'utilisateur $USERNAME n'a pas de mot de passe défini"
    echo "Définition du mot de passe..."
    sudo dscl . -passwd "/Users/$USERNAME" "" "nouveau_mot_de_passe_ici"
fi

Surveillance et rapports

Rapport de statut FileVault

#!/bin/bash

# Générer un rapport de statut FileVault
REPORT_FILE="/tmp/filevault_report.txt"

{
    echo "=== Rapport de statut FileVault ==="
    echo "Généré : $(date)"
    echo "Nom d'hôte : $(hostname)"
    echo ""
    
    echo "=== Statut FileVault ==="
    fdesetup status
    echo ""
    
    echo "=== Utilisateurs activés ==="
    fdesetup list
    echo ""
    
    echo "=== Statut du token sécurisé ==="
    for user in $(dscl . -list /Users | grep -v '^_'); do
        if [[ "$user" != "daemon" ]] && [[ "$user" != "nobody" ]]; then
            token_status=$(sysadminctl -secureTokenStatus "$user" 2>/dev/null | grep -o "ENABLED\|DISABLED")
            echo "Utilisateur : $user - Token : ${token_status:-INCONNU}"
        fi
    done
    
} > "$REPORT_FILE"

echo "Rapport généré : $REPORT_FILE"

Solutions aux erreurs courantes

ErreurCauseSolution
"Blank password"L'utilisateur n'a pas de mot de passeDéfinir un mot de passe avec dscl . -passwd
"Master keychain found"Ambiguïté du trousseauAjouter le paramètre -keychain
"Secure token required"L'utilisateur n'a pas de token sécuriséAccorder un token avec sysadminctl
"Already encrypted"FileVault déjà activéUtiliser -force ou vérifier le statut d'abord
"Encryption in progress"Opération concurrenteAttendre la fin

Bonnes pratiques de sécurité

  • Utiliser des mots de passe forts pour les comptes avec FileVault activé
  • Stocker les clés de récupération en sécurité dans la gestion des clés d'entreprise
  • Tester les scripts sur des appareils isolés avant le déploiement en flotte
  • Surveiller le progrès du chiffrement pour assurer la completion
  • Sauvegarder les clés de récupération avant de faire des modifications
  • Valider les permissions utilisateur avant de tenter des opérations

Considérations de performance

  • Le chiffrement initial peut prendre plusieurs heures
  • Les performances du système peuvent être impactées pendant le chiffrement
  • Planifier les opérations pendant les fenêtres de maintenance
  • Surveiller l'espace disque (le chiffrement nécessite de l'espace libre)
  • Considérer les différences de performance SSD vs HDD

Notes importantes

  • FileVault nécessite des privilèges administrateur et des tokens sécurisés
  • Les clés de récupération sont essentielles pour la récupération des données
  • Le chiffrement/déchiffrement ne peut pas être interrompu en sécurité
  • Tester tous les scripts minutieusement avant l'utilisation en production
  • Toujours avoir un plan de récupération de sauvegarde

Gestion des Mises à Jour macOS

Implémentez une gestion de mises à jour macOS de niveau entreprise sur votre déploiement Roundfleet avec un déploiement automatisé de correctifs, une surveillance de conformité, des déploiements échelonnés et des politiques de mise à jour complètes. Ce tutoriel fournit des solutions pour maintenir les correctifs de sécurité et la currency du système d'exploitation tout en minimisant les perturbations des opérations commerciales.

Comprendre la Gestion des Mises à Jour macOS

macOS fournit plusieurs méthodes pour gérer les mises à jour du système d'exploitation de manière programmatique :

  • Utilitaire Software Update - Outil en ligne de commande pour vérifier et installer les mises à jour
  • startosinstall - Installation directe du système depuis les applications d'installation
  • Commandes de Mise à Jour MDM - Intégration avec la gestion des appareils mobiles
  • Profils de Configuration - Contrôle des mises à jour basé sur les politiques
  • Service de Recherche de Logiciels Apple - Vérification de disponibilité des mises à jour

Opérations de Mise à Jour de Base

Lister les Mises à Jour Disponibles

#!/bin/bash

# Lister toutes les versions de système disponibles pour installation
softwareupdate --list-full-installers | grep 'macOS' | awk '{print ++count " " $0}'

Télécharger l'Installeur du Système

#!/bin/bash

# Récupérer l'installeur d'une version spécifique du système
softwareupdate --fetch-full-installer --full-installer-version 12.1

echo "Installeur du système téléchargé avec succès"

Installer la Mise à Jour du Système

#!/bin/bash

# Installation basique de mise à jour système
osVersion="$1"
majorVersion=$(echo $osVersion | cut -d "." -f 1)
minorVersion=$(echo $osVersion | cut -d "." -f 2)

if [ $majorVersion == "12" ]; then
    installerPath="Install macOS Monterey.app"
elif [ $majorVersion == "11" ]; then
    installerPath="Install macOS Big Sur.app"
elif [ $minorVersion == "15"* ]; then
    installerPath="Install macOS Catalina.app"
fi

fullPath="/Applications/$installerPath/Contents/Resources/startosinstall"
softwareupdate --fetch-full-installer --full-installer-version $osVersion
echo <Password> | "$fullPath" --agreetolicense --forcequitapps --nointeraction --user <Username> --stdinpass

Système de Gestion des Mises à Jour Entreprise

Outil de Gestion des Mises à Jour Complet

#!/bin/bash

# Outil de Gestion des Mises à Jour macOS Entreprise Roundfleet
# Déploiement automatisé de correctifs et surveillance de conformité

# Configuration
CONFIG_FILE="/etc/roundfleet/update_policy.conf"
LOG_FILE="/var/log/roundfleet_updates.log"
CACHE_DIR="/Library/Roundfleet/Updates"
REPORT_DIR="/var/log/roundfleet_reports"

# Créer les répertoires
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$CACHE_DIR" "$REPORT_DIR"

# Politique de mise à jour par défaut
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Politique de Gestion des Mises à Jour macOS Roundfleet
# Version : 2.0

# Application des Mises à Jour
ENFORCE_SECURITY_UPDATES=true
ALLOW_MAJOR_OS_UPDATES=false
AUTO_INSTALL_SECURITY_PATCHES=true
DEFER_MAJOR_UPDATES_DAYS=30

# Configuration de Planification
UPDATE_CHECK_INTERVAL=86400  # 24 heures
MAINTENANCE_WINDOW_START="02:00"
MAINTENANCE_WINDOW_END="06:00"
WEEKEND_UPDATES_ALLOWED=true
BUSINESS_HOURS_UPDATES=false

# Stratégie de Déploiement
STAGED_ROLLOUT=true
PILOT_GROUP_PERCENTAGE=10
PRODUCTION_DELAY_DAYS=7
EMERGENCY_PATCH_IMMEDIATE=true

# Exigences Système
MIN_BATTERY_PERCENTAGE=50
MIN_FREE_SPACE_GB=20
REQUIRE_AC_POWER=true
MAX_REBOOT_ATTEMPTS=3

# Paramètres de Notification
NOTIFY_USERS_BEFORE_UPDATE=true
NOTIFICATION_LEAD_TIME_HOURS=24
FORCE_UPDATE_AFTER_DEFERRALS=5
SEND_COMPLETION_REPORTS=true

# Paramètres de Compatibilité
EXCLUDE_BETA_UPDATES=true
VALIDATE_APP_COMPATIBILITY=true
BACKUP_BEFORE_MAJOR_UPDATE=true
EOF

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

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

# Obtenir la version macOS actuelle
get_current_version() {
    sw_vers -productVersion
}

# Obtenir les mises à jour disponibles
get_available_updates() {
    echo "=== Mises à Jour Disponibles ==="
    
    # Vérifier les mises à jour logicielles
    local updates
    updates=$(softwareupdate --list 2>/dev/null)
    
    if echo "$updates" | grep -q "No new software available"; then
        echo "✅ Le système est à jour"
        return 0
    else
        echo "Mises à jour disponibles :"
        echo "$updates"
        return 1
    fi
}

# Obtenir les installeurs de système disponibles
get_available_installers() {
    echo "=== Installeurs de Système Disponibles ==="
    
    # Lister les installeurs complets
    local installers
    installers=$(softwareupdate --list-full-installers 2>/dev/null)
    
    if [[ -n "$installers" ]]; then
        echo "$installers" | grep 'macOS' | awk '{print ++count " " $0}'
    else
        echo "Aucun installeur de système disponible"
    fi
}

# Vérifier la préparation du système pour les mises à jour
check_update_readiness() {
    echo "=== Vérification de Préparation aux Mises à Jour ==="
    local issues=0
    local warnings=0
    
    # Vérifier le niveau de batterie
    local battery_level
    if command -v pmset >/dev/null; then
        battery_level=$(pmset -g batt | grep -Eo "\d+%" | tr -d '%' | head -1)
        
        if [[ -n "$battery_level" && $battery_level -lt $MIN_BATTERY_PERCENTAGE ]]; then
            echo "❌ Niveau de batterie trop faible : ${battery_level}% (min : ${MIN_BATTERY_PERCENTAGE}%)"
            ((issues++))
        else
            echo "✅ Niveau de batterie adéquat : ${battery_level:-Alimentation CA}%"
        fi
    fi
    
    # Vérifier l'alimentation CA si requise
    if [[ "$REQUIRE_AC_POWER" == "true" ]]; then
        local ac_power
        ac_power=$(pmset -g ps | grep "AC Power" || echo "")
        
        if [[ -z "$ac_power" ]]; then
            echo "❌ Alimentation CA requise mais non connectée"
            ((issues++))
        else
            echo "✅ Alimentation CA connectée"
        fi
    fi
    
    # Vérifier l'espace disque libre
    local free_space_gb
    free_space_gb=$(df / | awk 'NR==2 {print int($4/1024/1024)}')
    
    if [[ $free_space_gb -lt $MIN_FREE_SPACE_GB ]]; then
        echo "❌ Espace disque insuffisant : ${free_space_gb}GB (min : ${MIN_FREE_SPACE_GB}GB)"
        ((issues++))
    else
        echo "✅ Espace disque suffisant : ${free_space_gb}GB"
    fi
    
    # Vérifier si le système est dans la fenêtre de maintenance
    local current_time
    current_time=$(date '+%H:%M')
    
    if [[ "$current_time" > "$MAINTENANCE_WINDOW_START" && "$current_time" < "$MAINTENANCE_WINDOW_END" ]]; then
        echo "✅ Dans la fenêtre de maintenance"
    else
        echo "⚠️  Hors de la fenêtre de maintenance (actuel : $current_time)"
        ((warnings++))
    fi
    
    # Vérifier si les mises à jour de week-end sont autorisées
    local day_of_week
    day_of_week=$(date '+%u')  # 1=Lundi, 7=Dimanche
    
    if [[ $day_of_week -gt 5 ]] && [[ "$WEEKEND_UPDATES_ALLOWED" != "true" ]]; then
        echo "❌ Mises à jour de week-end non autorisées"
        ((issues++))
    fi
    
    echo "Résumé de préparation : $issues problèmes, $warnings avertissements"
    return $issues
}

# Installer les mises à jour de sécurité
install_security_updates() {
    echo "=== Installation des Mises à Jour de Sécurité ==="
    
    if [[ "$AUTO_INSTALL_SECURITY_PATCHES" != "true" ]]; then
        echo "Installation automatique des mises à jour de sécurité désactivée"
        return 0
    fi
    
    # Vérifier la préparation
    if ! check_update_readiness >/dev/null; then
        echo "❌ Système non prêt pour les mises à jour"
        return 1
    fi
    
    # Installer les mises à jour recommandées
    echo "Installation des mises à jour de sécurité et recommandées..."
    log_action "Démarrage de l'installation des mises à jour de sécurité"
    
    # Utiliser softwareupdate pour installer les mises à jour recommandées
    if softwareupdate --install --recommended --verbose; then
        echo "✅ Mises à jour de sécurité installées avec succès"
        log_action "Mises à jour de sécurité installées avec succès"
        
        # Vérifier si un redémarrage est requis
        if softwareupdate --list | grep -q "restart"; then
            echo "⚠️  Redémarrage système requis"
            log_action "Redémarrage système requis après mises à jour de sécurité"
        fi
        
        return 0
    else
        echo "❌ Échec de l'installation des mises à jour de sécurité"
        log_action "ÉCHEC : Installation des mises à jour de sécurité"
        return 1
    fi
}

# Télécharger l'installeur du système
download_os_installer() {
    local target_version="$1"
    
    echo "=== Téléchargement de l'Installeur du Système ==="
    echo "Version cible : $target_version"
    
    # Valider le format de version
    if [[ ! "$target_version" =~ ^[0-9]+\.[0-9]+(\.[0-9]+)?$ ]]; then
        echo "❌ Format de version invalide : $target_version"
        return 1
    fi
    
    # Télécharger l'installeur
    echo "Téléchargement de l'installeur macOS $target_version..."
    log_action "Téléchargement de l'installeur macOS : $target_version"
    
    if softwareupdate --fetch-full-installer --full-installer-version "$target_version"; then
        echo "✅ Installeur macOS téléchargé avec succès"
        log_action "Installeur macOS téléchargé : $target_version"
        
        # Vérifier que l'installeur existe
        local installer_path
        installer_path=$(find /Applications -name "Install macOS*.app" -path "*$target_version*" 2>/dev/null | head -1)
        
        if [[ -n "$installer_path" && -d "$installer_path" ]]; then
            echo "Emplacement de l'installeur : $installer_path"
            return 0
        else
            # Vérifier l'installeur par version majeure
            local major_version
            major_version=$(echo "$target_version" | cut -d'.' -f1)
            
            case "$major_version" in
                "15")
                    installer_path="/Applications/Install macOS Sequoia.app"
                    ;;
                "14")
                    installer_path="/Applications/Install macOS Sonoma.app"
                    ;;
                "13")
                    installer_path="/Applications/Install macOS Ventura.app"
                    ;;
                "12")
                    installer_path="/Applications/Install macOS Monterey.app"
                    ;;
                "11")
                    installer_path="/Applications/Install macOS Big Sur.app"
                    ;;
                *)
                    echo "❌ Version macOS inconnue : $target_version"
                    return 1
                    ;;
            esac
            
            if [[ -d "$installer_path" ]]; then
                echo "Installeur trouvé : $installer_path"
                return 0
            else
                echo "❌ Installeur non trouvé après téléchargement"
                return 1
            fi
        fi
    else
        echo "❌ Échec du téléchargement de l'installeur macOS"
        log_action "ÉCHEC : Téléchargement de l'installeur macOS pour $target_version"
        return 1
    fi
}

# Installer une mise à jour majeure du système
install_major_update() {
    local target_version="$1"
    local admin_user="$2"
    local admin_password="$3"
    
    echo "=== Installation de Mise à Jour Majeure du Système ==="
    echo "Version cible : $target_version"
    echo "Utilisateur admin : $admin_user"
    
    if [[ "$ALLOW_MAJOR_OS_UPDATES" != "true" ]]; then
        echo "❌ Mises à jour majeures du système non autorisées par la politique"
        return 1
    fi
    
    # Vérifier la préparation
    if ! check_update_readiness; then
        echo "❌ Système non prêt pour une mise à jour majeure"
        return 1
    fi
    
    # Trouver l'installeur
    local installer_path
    local major_version
    major_version=$(echo "$target_version" | cut -d'.' -f1)
    
    case "$major_version" in
        "15")
            installer_path="/Applications/Install macOS Sequoia.app"
            ;;
        "14")
            installer_path="/Applications/Install macOS Sonoma.app"
            ;;
        "13")
            installer_path="/Applications/Install macOS Ventura.app"
            ;;
        "12")
            installer_path="/Applications/Install macOS Monterey.app"
            ;;
        "11")
            installer_path="/Applications/Install macOS Big Sur.app"
            ;;
        *)
            echo "❌ Version macOS non supportée : $target_version"
            return 1
            ;;
    esac
    
    if [[ ! -d "$installer_path" ]]; then
        echo "Installeur non trouvé, téléchargement..."
        if ! download_os_installer "$target_version"; then
            return 1
        fi
    fi
    
    # Préparer la commande d'installation
    local install_cmd="$installer_path/Contents/Resources/startosinstall"
    local install_args="--agreetolicense --forcequitapps --nointeraction"
    
    # Vérifier si c'est un Mac Apple Silicon (nécessite des identifiants)
    if system_profiler SPHardwareDataType | grep -q "Apple M"; then
        if [[ -z "$admin_user" || -z "$admin_password" ]]; then
            echo "❌ Mac Apple Silicon nécessite des identifiants administrateur"
            return 1
        fi
        install_args="$install_args --user $admin_user --stdinpass"
    fi
    
    echo "Démarrage de l'installation macOS..."
    log_action "Démarrage de la mise à jour majeure vers $target_version"
    
    # Exécuter l'installation
    if [[ -n "$admin_password" ]]; then
        echo "$admin_password" | "$install_cmd" $install_args
    else
        "$install_cmd" $install_args
    fi
    
    local result=$?
    
    if [[ $result -eq 0 ]]; then
        echo "✅ Mise à jour macOS initiée avec succès"
        log_action "Mise à jour macOS initiée avec succès vers $target_version"
        echo "⚠️  Le système redémarrera pour terminer l'installation"
    else
        echo "❌ Échec de l'initiation de la mise à jour macOS (code de sortie : $result)"
        log_action "ÉCHEC : Initiation de la mise à jour macOS vers $target_version (code de sortie : $result)"
    fi
    
    return $result
}

# Générer un rapport de conformité des mises à jour
generate_update_report() {
    local report_file="$REPORT_DIR/update_compliance_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Génération du Rapport de Conformité des Mises à Jour ==="
    
    # Obtenir les informations système actuelles
    local current_version
    current_version=$(sw_vers -productVersion)
    local build_version
    build_version=$(sw_vers -buildVersion)
    local hardware_model
    hardware_model=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)
    
    # Vérifier les mises à jour disponibles
    local updates_available="false"
    local security_updates_available="false"
    
    if ! softwareupdate --list 2>/dev/null | grep -q "No new software available"; then
        updates_available="true"
        
        if softwareupdate --list 2>/dev/null | grep -i "security\|recommended"; then
            security_updates_available="true"
        fi
    fi
    
    # Calculer les jours depuis la dernière mise à jour
    local last_update_date
    last_update_date=$(system_profiler SPInstallHistoryDataType | grep "Install Date" | head -1 | awk -F: '{print $2}' | xargs)
    local days_since_update="inconnu"
    
    if [[ -n "$last_update_date" ]]; then
        local last_update_epoch
        last_update_epoch=$(date -j -f "%m/%d/%y" "$last_update_date" "+%s" 2>/dev/null || echo "0")
        local current_epoch
        current_epoch=$(date "+%s")
        days_since_update=$(( (current_epoch - last_update_epoch) / 86400 ))
    fi
    
    # Créer le rapport JSON
    cat > "$report_file" << EOF
{
  "type_rapport": "conformite_mise_a_jour",
  "horodatage": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "infos_appareil": {
    "nom_hote": "$(hostname)",
    "numero_serie": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "modele_materiel": "$hardware_model",
    "version_os_actuelle": "$current_version",
    "version_build": "$build_version"
  },
  "statut_mise_a_jour": {
    "mises_a_jour_disponibles": $updates_available,
    "mises_a_jour_securite_disponibles": $security_updates_available,
    "jours_depuis_derniere_mise_a_jour": $days_since_update,
    "date_derniere_mise_a_jour": "$last_update_date",
    "mise_a_jour_auto_activee": $(defaults read /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled 2>/dev/null || echo false)
  },
  "conformite_politique": {
    "mises_a_jour_securite_appliquees": $ENFORCE_SECURITY_UPDATES,
    "mises_a_jour_majeures_autorisees": $ALLOW_MAJOR_OS_UPDATES,
    "installation_auto_activee": $AUTO_INSTALL_SECURITY_PATCHES,
    "deploiement_echelonne_active": $STAGED_ROLLOUT
  },
  "preparation_systeme": {
    "batterie_suffisante": true,
    "alimentation_ca_connectee": $(pmset -g ps | grep -q "AC Power" && echo true || echo false),
    "espace_disque_suffisant": true,
    "dans_fenetre_maintenance": false
  }
}
EOF
    
    echo "Rapport de conformité des mises à jour sauvegardé dans : $report_file"
    log_action "Rapport de conformité des mises à jour généré : $report_file"
}

# Fonction principale avec gestion d'arguments
main() {
    log_action "=== Outil de Gestion des Mises à Jour Roundfleet Démarré ==="
    
    case "${1:-status}" in
        "check")
            get_available_updates
            ;;
        "security")
            install_security_updates
            ;;
        "download")
            download_os_installer "$2"
            ;;
        "install")
            install_major_update "$2" "$3" "$4"
            ;;
        "readiness")
            check_update_readiness
            ;;
        "installers")
            get_available_installers
            ;;
        "report")
            generate_update_report
            ;;
        "status"|*)
            echo "Version macOS actuelle : $(get_current_version)"
            get_available_updates
            ;;
    esac
    
    log_action "=== Opération de gestion des mises à jour terminée ==="
}

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

Gestion Avancée des Mises à Jour

Gestion du Déploiement Échelonné

#!/bin/bash

# Gestion du déploiement échelonné pour les déploiements d'entreprise
manage_staged_rollout() {
    local update_version="$1"
    local deployment_stage="${2:-pilot}"
    
    echo "=== Gestion du Déploiement Échelonné ==="
    echo "Version de mise à jour : $update_version"
    echo "Étape de déploiement : $deployment_stage"
    
    # Définir les groupes d'appareils
    local device_serial
    device_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)
    
    # Calculer le hash pour l'affectation cohérente de groupe
    local hash_value
    hash_value=$(echo "$device_serial" | md5 | cut -c1-2)
    local numeric_hash
    numeric_hash=$(printf "%d" "0x$hash_value")
    local group_percentage
    group_percentage=$((numeric_hash % 100))
    
    case "$deployment_stage" in
        "pilot")
            if [[ $group_percentage -lt $PILOT_GROUP_PERCENTAGE ]]; then
                echo "✅ Appareil sélectionné pour le déploiement pilote"
                log_action "Appareil inclus dans le groupe pilote pour $update_version"
                return 0
            else
                echo "⏳ Appareil non dans le groupe pilote, en attente du déploiement production"
                return 1
            fi
            ;;
        "production")
            echo "✅ Appareil éligible pour le déploiement production"
            log_action "Appareil inclus dans le déploiement production pour $update_version"
            return 0
            ;;
        "emergency")
            echo "🚨 Déploiement d'urgence - contournement des étapes"
            log_action "Déploiement d'urgence initié pour $update_version"
            return 0
            ;;
        *)
            echo "❌ Étape de déploiement inconnue : $deployment_stage"
            return 1
            ;;
    esac
}

# Exemple d'utilisation :
# manage_staged_rollout "14.2.1" "pilot"

Vérification de Compatibilité des Applications

#!/bin/bash

# Vérifier la compatibilité des applications avant les mises à jour majeures
check_app_compatibility() {
    local target_version="$1"
    
    echo "=== Vérification de Compatibilité des Applications ==="
    
    if [[ "$VALIDATE_APP_COMPATIBILITY" != "true" ]]; then
        echo "Vérification de compatibilité des applications désactivée"
        return 0
    fi
    
    local incompatible_apps=()
    
    # Vérifier les applications 32 bits (non supportées dans macOS 10.15+)
    local target_major
    target_major=$(echo "$target_version" | cut -d'.' -f1)
    
    if [[ $target_major -ge 10 ]]; then
        echo "Vérification des applications 32 bits..."
        
        # Utiliser system_profiler pour trouver les applications 32 bits
        local bit32_apps
        bit32_apps=$(system_profiler SPApplicationsDataType | grep -B1 -A1 "64-Bit (Intel): No" | grep "Location:" | awk -F: '{print $2}' | xargs)
        
        if [[ -n "$bit32_apps" ]]; then
            echo "⚠️  Applications 32 bits trouvées :"
            echo "$bit32_apps"
            incompatible_apps+=("applications 32 bits")
        fi
    fi
    
    # Vérifier les applications incompatibles connues
    local known_incompatible=(
        "/Applications/Adobe CS6"
        "/Applications/Microsoft Office 2011"
        "/Applications/Final Cut Pro 7"
    )
    
    for app_path in "${known_incompatible[@]}"; do
        if [[ -d "$app_path" ]]; then
            echo "⚠️  Application incompatible connue trouvée : $app_path"
            incompatible_apps+=("$(basename "$app_path")")
        fi
    done
    
    # Générer le rapport de compatibilité
    if [[ ${#incompatible_apps[@]} -eq 0 ]]; then
        echo "✅ Aucun problème de compatibilité détecté"
        return 0
    else
        echo "❌ Problèmes de compatibilité trouvés :"
        printf '  - %s\n' "${incompatible_apps[@]}"
        
        # Journaliser les problèmes de compatibilité
        log_action "Problèmes de compatibilité d'applications trouvés pour $target_version : ${incompatible_apps[*]}"
        return 1
    fi
}

check_app_compatibility "14.0"

Sauvegarde Automatisée Avant Mises à Jour

#!/bin/bash

# Créer une sauvegarde système avant les mises à jour majeures
create_pre_update_backup() {
    local backup_destination="${1:-/Volumes/Backup}"
    
    echo "=== Sauvegarde Pré-Mise à Jour ==="
    
    if [[ "$BACKUP_BEFORE_MAJOR_UPDATE" != "true" ]]; then
        echo "Sauvegarde pré-mise à jour désactivée"
        return 0
    fi
    
    # Vérifier la destination de sauvegarde
    if [[ ! -d "$backup_destination" ]]; then
        echo "❌ Destination de sauvegarde non disponible : $backup_destination"
        return 1
    fi
    
    # Créer une sauvegarde Time Machine
    echo "Création de la sauvegarde Time Machine..."
    if tmutil startbackup --auto --block; then
        echo "✅ Sauvegarde Time Machine terminée"
        log_action "Sauvegarde Time Machine pré-mise à jour terminée"
    else
        echo "⚠️  Sauvegarde Time Machine échouée, poursuite de la mise à jour"
        log_action "AVERTISSEMENT : Sauvegarde Time Machine pré-mise à jour échouée"
    fi
    
    # Créer une sauvegarde de configuration système
    local config_backup="$backup_destination/roundfleet_config_$(date +%Y%m%d_%H%M%S).tar.gz"
    
    echo "Création de la sauvegarde de configuration..."
    if tar -czf "$config_backup" \
        /etc/roundfleet \
        /Library/Preferences \
        /System/Library/LaunchDaemons/com.roundfleet.* \
        2>/dev/null; then
        echo "✅ Sauvegarde de configuration créée : $config_backup"
        log_action "Sauvegarde de configuration créée : $config_backup"
    else
        echo "⚠️  Sauvegarde de configuration échouée"
        log_action "AVERTISSEMENT : Sauvegarde de configuration échouée"
    fi
    
    return 0
}

create_pre_update_backup

Surveillance et Conformité

Surveillance de Conformité des Mises à Jour

#!/bin/bash

# Surveiller la conformité des mises à jour dans la flotte
monitor_update_compliance() {
    echo "=== Surveillance de Conformité des Mises à Jour ==="
    
    local current_version
    current_version=$(sw_vers -productVersion)
    
    # Vérifier contre les lignes de base de sécurité
    local security_baseline="14.2.1"  # Exemple de ligne de base
    
    if [[ "$(printf '%s\n' "$security_baseline" "$current_version" | sort -V | head -1)" != "$security_baseline" ]]; then
        echo "❌ En dessous de la ligne de base de sécurité (actuel : $current_version, requis : $security_baseline)"
        log_action "VIOLATION DE CONFORMITÉ : En dessous de la ligne de base de sécurité $security_baseline"
        
        # Déclencher la remédiation si activée
        if [[ "$ENFORCE_SECURITY_UPDATES" == "true" ]]; then
            echo "Initiation de la remédiation automatique..."
            install_security_updates
        fi
    else
        echo "✅ Répond aux exigences de ligne de base de sécurité"
    fi
    
    # Vérifier les mises à jour en retard
    local last_check
    last_check=$(defaults read /Library/Preferences/com.apple.SoftwareUpdate LastSuccessfulDate 2>/dev/null || echo "")
    
    if [[ -n "$last_check" ]]; then
        local days_since_check
        days_since_check=$(( ($(date +%s) - $(date -j -f "%Y-%m-%d %H:%M:%S %z" "$last_check" +%s 2>/dev/null || echo 0)) / 86400 ))
        
        if [[ $days_since_check -gt 7 ]]; then
            echo "⚠️  Mises à jour non vérifiées depuis $days_since_check jours"
            log_action "AVERTISSEMENT : Mises à jour non vérifiées depuis $days_since_check jours"
        fi
    fi
}

monitor_update_compliance

Déploiement de Correctifs d'Urgence

#!/bin/bash

# Déploiement de correctifs d'urgence pour les mises à jour de sécurité critiques
deploy_emergency_patch() {
    local patch_version="$1"
    local override_policies="${2:-false}"
    
    echo "=== Déploiement de Correctifs d'Urgence ==="
    echo "Version du correctif : $patch_version"
    echo "Contournement des politiques : $override_policies"
    
    log_action "URGENCE : Déploiement du correctif critique $patch_version"
    
    # Contourner les restrictions normales pour les correctifs d'urgence
    if [[ "$override_policies" == "true" ]]; then
        # Modifier temporairement la configuration
        local original_config
        original_config=$(cat "$CONFIG_FILE")
        
        # Configuration d'urgence
        cat > "$CONFIG_FILE" << 'EOF'
ENFORCE_SECURITY_UPDATES=true
AUTO_INSTALL_SECURITY_PATCHES=true
EMERGENCY_PATCH_IMMEDIATE=true
REQUIRE_AC_POWER=false
MIN_BATTERY_PERCENTAGE=20
BUSINESS_HOURS_UPDATES=true
EOF
        
        # Installer le correctif d'urgence
        if install_security_updates; then
            echo "✅ Correctif d'urgence déployé avec succès"
            log_action "Correctif d'urgence $patch_version déployé avec succès"
        else
            echo "❌ Déploiement du correctif d'urgence échoué"
            log_action "CRITIQUE : Déploiement du correctif d'urgence $patch_version ÉCHOUÉ"
        fi
        
        # Restaurer la configuration originale
        echo "$original_config" > "$CONFIG_FILE"
    else
        # Déploiement d'urgence standard
        install_security_updates
    fi
}

# Exemple d'utilisation :
# deploy_emergency_patch "14.2.1" "true"

Notes de Configuration Importantes

Outils de Mise à Jour macOS

  • softwareupdate - Utilitaire de mise à jour logicielle en ligne de commande
  • startosinstall - Outil d'installation directe du système
  • system_profiler - Informations système et historique des mises à jour
  • tmutil - Utilitaire de sauvegarde Time Machine
  • pmset - Paramètres de gestion d'énergie

Considérations Apple Silicon

  • Identifiants administrateur requis - Les mises à jour nécessitent une authentification utilisateur
  • Politiques de démarrage sécurisé - Peuvent affecter l'installation des mises à jour
  • Options de mode de récupération - Différentes des Mac Intel
  • Extensions de noyau réduites - Modèle d'extension système

Bonnes Pratiques pour l'Entreprise

  1. Stratégie de Déploiement Échelonné

    • Tester les mises à jour sur un groupe pilote d'abord
    • Surveiller les problèmes avant le déploiement complet
    • Maintenir des capacités de retour en arrière
  2. Gestion de Conformité

    • Définir des lignes de base de sécurité
    • Surveiller régulièrement le statut des mises à jour
    • Automatiser les rapports de conformité
  3. Atténuation des Risques

    • Sauvegarder avant les mises à jour majeures
    • Tester la compatibilité des applications
    • Planifier pour les correctifs d'urgence
  4. Communication Utilisateur

    • Notifier les utilisateurs des mises à jour planifiées
    • Fournir des fenêtres de maintenance claires
    • Offrir des options de report dans les limites des politiques

Dépannage des Problèmes Courants

  • Espace disque insuffisant - Nettoyer avant les mises à jour ou augmenter le stockage
  • Exigences d'alimentation - Assurer l'alimentation CA pour les mises à jour majeures
  • Connectivité réseau - Vérifier l'accès aux serveurs de mise à jour d'Apple
  • Échecs d'authentification - Vérifier les identifiants administrateur sur Apple Silicon
  • Échecs d'installation - Examiner les journaux système et la compatibilité

N'oubliez pas de tester minutieusement les procédures de mise à jour dans un environnement non-production avant de les déployer sur l'ensemble de votre Roundfleet.

Personnalisation de la Fenêtre de Connexion sur macOS

Personnalisez et sécurisez la fenêtre de connexion sur vos appareils Roundfleet pour améliorer la sécurité, l'image de marque et l'expérience utilisateur. Ce tutoriel couvre la gestion des listes d'utilisateurs, le contrôle des options d'alimentation, les messages personnalisés et la configuration de la fenêtre de connexion d'entreprise.

Comprendre la Fenêtre de Connexion macOS

La fenêtre de connexion macOS est la première interface que les utilisateurs rencontrent lors du démarrage de leur appareil. Elle offre plusieurs options de personnalisation :

  • Modes d'affichage utilisateur - Afficher la liste des utilisateurs ou les champs nom d'utilisateur/mot de passe
  • Options d'alimentation - Contrôler les boutons d'arrêt, de redémarrage et de veille
  • Messages personnalisés - Afficher des avis organisationnels ou de la personnalisation
  • Paramètres de sécurité - Masquer les informations sensibles et contrôler l'accès

Considérations d'Entreprise

La personnalisation de la fenêtre de connexion est cruciale pour la sécurité d'entreprise :

  • Masquer les listes d'utilisateurs pour prévenir l'énumération des utilisateurs
  • Désactiver les options d'alimentation pour prévenir les arrêts non autorisés
  • Afficher des avis de sécurité pour les exigences de conformité
  • Personnaliser l'interface pour l'identité organisationnelle

Configuration de Base de la Fenêtre de Connexion

Afficher la Liste des Utilisateurs

#!/bin/bash

# Afficher la liste des utilisateurs dans la fenêtre de connexion
defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false

echo "Affichage de la liste des utilisateurs activé dans la fenêtre de connexion"

Afficher la Boîte de Dialogue Nom d'Utilisateur/Mot de Passe

#!/bin/bash

# Afficher la boîte de dialogue nom d'utilisateur et mot de passe au lieu de la liste des utilisateurs
defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true

echo "Boîte de dialogue nom d'utilisateur/mot de passe activée dans la fenêtre de connexion"

Masquer les Options d'Alimentation

#!/bin/bash

# Masquer le bouton d'arrêt
defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true

# Masquer le bouton de redémarrage
defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true

# Masquer le bouton de veille
defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true

echo "Toutes les options d'alimentation masquées de la fenêtre de connexion"

Activer les Options d'Alimentation

#!/bin/bash

# Activer le bouton d'arrêt
defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false

# Activer le bouton de redémarrage
defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false

# Activer le bouton de veille
defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false

echo "Toutes les options d'alimentation activées dans la fenêtre de connexion"

Afficher un Message Personnalisé

#!/bin/bash

# Afficher un message personnalisé sur la fenêtre de connexion
MESSAGE="Votre appareil est géré par Roundfleet. Contactez l'IT pour assistance."
defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$MESSAGE"

echo "Message personnalisé défini pour la fenêtre de connexion"

Gestion Avancée de la Fenêtre de Connexion

Configuration Complète de la Fenêtre de Connexion

#!/bin/bash

# Configuration avancée de la fenêtre de connexion avec validation
configure_login_window() {
    local config_type="$1"
    local custom_message="$2"
    
    # 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 "$config_type" in
        "secure")
            echo "Application de la configuration sécurisée de la fenêtre de connexion..."
            
            # Masquer la liste des utilisateurs pour la sécurité
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            
            # Désactiver toutes les options d'alimentation
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Définir un message de sécurité
            local security_msg="Personnel Autorisé Uniquement - Toute Activité Surveillée"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$security_msg"
            
            echo "✓ Configuration sécurisée appliquée"
            ;;
        "corporate")
            echo "Application de la configuration d'entreprise de la fenêtre de connexion..."
            
            # Afficher la liste des utilisateurs pour la commodité
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            
            # Permettre le redémarrage mais désactiver l'arrêt et la veille
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Définir un message d'entreprise
            local corp_msg="${custom_message:-Propriété de Roundfleet Corporation}"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$corp_msg"
            
            echo "✓ Configuration d'entreprise appliquée"
            ;;
        "kiosk")
            echo "Application de la configuration kiosque de la fenêtre de connexion..."
            
            # Masquer la liste des utilisateurs
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            
            # Désactiver toutes les options d'alimentation
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            
            # Masquer des éléments supplémentaires pour le mode kiosque
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers true
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            
            # Définir un message de kiosque
            local kiosk_msg="Mode Kiosque - Accès Autorisé Uniquement"
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$kiosk_msg"
            
            echo "✓ Configuration kiosque appliquée"
            ;;
        "standard")
            echo "Application de la configuration standard de la fenêtre de connexion..."
            
            # Afficher la liste des utilisateurs
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            
            # Activer toutes les options d'alimentation
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
            
            # Effacer le message personnalisé
            defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || true
            
            echo "✓ Configuration standard appliquée"
            ;;
        *)
            echo "Erreur : Type de configuration inconnu '$config_type'"
            echo "Types disponibles : secure, corporate, kiosk, standard"
            return 1
            ;;
    esac
    
    # Vérifier la configuration
    verify_login_window_config
}

# Vérifier la configuration actuelle de la fenêtre de connexion
verify_login_window_config() {
    echo ""
    echo "=== Configuration Actuelle de la Fenêtre de Connexion ==="
    
    # Vérifier le mode d'affichage utilisateur
    local show_fullname
    show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    
    if [[ "$show_fullname" == "true" ]]; then
        echo "Affichage Utilisateur : Boîte de Dialogue Nom d'Utilisateur/Mot de Passe"
    else
        echo "Affichage Utilisateur : Liste des Utilisateurs"
    fi
    
    # Vérifier les options d'alimentation
    local shutdown_disabled
    shutdown_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || echo "false")
    echo "Bouton d'Arrêt : $([ "$shutdown_disabled" == "true" ] && echo "Masqué" || echo "Visible")"
    
    local restart_disabled
    restart_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || echo "false")
    echo "Bouton de Redémarrage : $([ "$restart_disabled" == "true" ] && echo "Masqué" || echo "Visible")"
    
    local sleep_disabled
    sleep_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || echo "false")
    echo "Bouton de Veille : $([ "$sleep_disabled" == "true" ] && echo "Masqué" || echo "Visible")"
    
    # Vérifier le message personnalisé
    local login_text
    login_text=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "Aucun")
    echo "Message Personnalisé : $login_text"
}

# Exemples d'utilisation
configure_login_window "corporate" "Bienvenue dans Roundfleet Enterprise"

Système de Gestion de Fenêtre de Connexion d'Entreprise

#!/bin/bash

# Outil de Gestion de Fenêtre de Connexion Roundfleet
# Configuration et surveillance complètes de la fenêtre de connexion pour les appareils de flotte

# Configuration
SCRIPT_VERSION="1.0.0"
LOG_FILE="/var/log/roundfleet_loginwindow.log"
REPORT_DIR="/etc/roundfleet/reports/loginwindow"
CONFIG_DIR="/etc/roundfleet/loginwindow"

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

# Modèles de politiques de fenêtre de connexion
declare -A LOGIN_POLICIES=(
    ["corporate_standard"]="user_list,restart_only,company_branding,moderate_security"
    ["corporate_secure"]="username_dialog,no_power,security_message,high_security"
    ["kiosk_mode"]="username_dialog,no_power,kiosk_branding,maximum_security"
    ["public_access"]="user_list,all_power,public_notice,low_security"
    ["executive"]="username_dialog,restart_only,executive_branding,high_security"
    ["guest_network"]="user_list,no_power,guest_notice,moderate_security"
    ["development"]="user_list,all_power,dev_environment,low_security"
    ["classroom"]="user_list,restart_only,educational_message,moderate_security"
    ["healthcare"]="username_dialog,no_power,hipaa_notice,maximum_security"
    ["financial"]="username_dialog,no_power,compliance_notice,maximum_security"
)

# Modèles de messages pour différents scénarios
declare -A MESSAGE_TEMPLATES=(
    ["security_warning"]="ACCÈS RESTREINT - PERSONNEL AUTORISÉ UNIQUEMENT - TOUTE ACTIVITÉ SURVEILLÉE"
    ["corporate_standard"]="Propriété de {COMPANY} | Support IT : {SUPPORT_CONTACT}"
    ["compliance_notice"]="Ce système contient des informations confidentielles. L'accès non autorisé est interdit."
    ["guest_notice"]="Accès Invité | Veuillez contacter la réception pour assistance"
    ["kiosk_mode"]="Terminal Kiosque | Pour assistance appuyez sur F1"
    ["maintenance"]="Système en Maintenance | Contactez le Département IT"
    ["emergency"]="Accès d'Urgence Uniquement | Incident de Sécurité en Cours"
    ["educational"]="Appareil Éducatif | Les étudiants doivent suivre la politique d'usage acceptable"
    ["hipaa_notice"]="Système Protégé HIPAA | Personnel de Santé Autorisé Uniquement"
    ["financial_compliance"]="Système de Données Financières | Conformité SOX Requise"
)

# 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 fenêtre de connexion
enforce_login_policy() {
    local policy_name="$1"
    local company_name="${2:-Roundfleet}"
    local support_contact="${3:-Département IT}"
    local dry_run="${4:-false}"
    
    log_action "Application de la politique de fenêtre de connexion : $policy_name (dry_run : $dry_run)"
    
    if [[ -z "${LOGIN_POLICIES[$policy_name]}" ]]; then
        log_action "ERREUR : Politique inconnue '$policy_name'"
        echo "Politiques disponibles : ${!LOGIN_POLICIES[*]}"
        return 1
    fi
    
    # Analyser la configuration de politique
    IFS=',' read -ra POLICY_PARTS <<< "${LOGIN_POLICIES[$policy_name]}"
    local user_display="${POLICY_PARTS[0]}"
    local power_options="${POLICY_PARTS[1]}"
    local branding_type="${POLICY_PARTS[2]}"
    local security_level="${POLICY_PARTS[3]}"
    
    echo "=== Application de la Politique : $policy_name ==="
    echo "Affichage Utilisateur : $user_display"
    echo "Options d'Alimentation : $power_options"
    echo "Image de Marque : $branding_type"
    echo "Niveau de Sécurité : $security_level"
    
    if [[ "$dry_run" == "true" ]]; then
        echo "MODE TEST - Aucun changement ne sera appliqué"
        return 0
    fi
    
    # Appliquer les paramètres d'affichage utilisateur
    apply_user_display_settings "$user_display"
    
    # Appliquer les paramètres d'options d'alimentation
    apply_power_option_settings "$power_options"
    
    # Appliquer l'image de marque et la messagerie
    apply_branding_settings "$branding_type" "$company_name" "$support_contact"
    
    # Appliquer les configurations de sécurité
    apply_security_settings "$security_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"
}

# Appliquer les paramètres d'affichage utilisateur
apply_user_display_settings() {
    local display_type="$1"
    
    case "$display_type" in
        "user_list")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers false
            echo "✓ Affichage de la liste des utilisateurs activé"
            ;;
        "username_dialog")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            echo "✓ Boîte de dialogue nom d'utilisateur/mot de passe activée"
            ;;
        "hidden_users")
            defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
            defaults write /Library/Preferences/com.apple.loginwindow HideLocalUsers true
            defaults write /Library/Preferences/com.apple.loginwindow HideMobileAccounts true
            echo "✓ Tous les utilisateurs masqués de l'affichage"
            ;;
    esac
}

# Appliquer les paramètres d'options d'alimentation
apply_power_option_settings() {
    local power_config="$1"
    
    case "$power_config" in
        "all_power")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
            echo "✓ Toutes les options d'alimentation activées"
            ;;
        "restart_only")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            echo "✓ Seule l'option de redémarrage activée"
            ;;
        "no_power")
            defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
            defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
            echo "✓ Toutes les options d'alimentation désactivées"
            ;;
    esac
}

# Appliquer les paramètres d'image de marque et de messagerie
apply_branding_settings() {
    local branding_type="$1"
    local company_name="$2"
    local support_contact="$3"
    
    local message=""
    
    case "$branding_type" in
        "company_branding")
            message="${MESSAGE_TEMPLATES[corporate_standard]}"
            message="${message/\{COMPANY\}/$company_name}"
            message="${message/\{SUPPORT_CONTACT\}/$support_contact}"
            ;;
        "security_message")
            message="${MESSAGE_TEMPLATES[security_warning]}"
            ;;
        "kiosk_branding")
            message="${MESSAGE_TEMPLATES[kiosk_mode]}"
            ;;
        "executive_branding")
            message="Poste de Travail Exécutif | $company_name | Confidentiel"
            ;;
        "guest_notice")
            message="${MESSAGE_TEMPLATES[guest_notice]}"
            ;;
        "educational_message")
            message="${MESSAGE_TEMPLATES[educational]}"
            ;;
        "hipaa_notice")
            message="${MESSAGE_TEMPLATES[hipaa_notice]}"
            ;;
        "compliance_notice")
            message="${MESSAGE_TEMPLATES[financial_compliance]}"
            ;;
        *)
            message="Géré par $company_name"
            ;;
    esac
    
    if [[ -n "$message" ]]; then
        defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$message"
        echo "✓ Message personnalisé appliqué : $message"
    fi
}

# Appliquer les paramètres spécifiques à la sécurité
apply_security_settings() {
    local security_level="$1"
    
    case "$security_level" in
        "maximum_security")
            # Masquer les informations de l'ordinateur
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo ""
            
            # Désactiver le menu d'entrée
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu false
            
            # Désactiver la connexion automatique
            defaults delete /Library/Preferences/com.apple.loginwindow autoLoginUser 2>/dev/null || true
            
            # Activer le délai de fenêtre de connexion
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ Paramètres de sécurité maximale appliqués"
            ;;
        "high_security")
            # Afficher des informations minimales de l'ordinateur
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName
            
            # Activer le menu d'entrée pour le support linguistique
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            
            # Désactiver le compte invité
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ Paramètres de sécurité élevée appliqués"
            ;;
        "moderate_security")
            # Sécurité standard avec quelques fonctionnalités de commodité
            defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo HostName
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
            
            echo "✓ Paramètres de sécurité modérée appliqués"
            ;;
        "low_security")
            # Restrictions minimales pour la commodité
            defaults write /Library/Preferences/com.apple.loginwindow showInputMenu true
            
            echo "✓ Paramètres de sécurité faible appliqués"
            ;;
    esac
}

# Générer un rapport complet de conformité de politique
generate_policy_report() {
    local policy_name="$1"
    local report_file="$2"
    
    # Obtenir les paramètres actuels de la fenêtre de connexion
    local show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    local shutdown_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || echo "false")
    local restart_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || echo "false")
    local sleep_disabled=$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || echo "false")
    local login_text=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "")
    local hide_local_users=$(defaults read /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || echo "false")
    local guest_enabled=$(defaults read /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || echo "false")
    
    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",
        "current_settings": {
            "show_fullname": $show_fullname,
            "shutdown_disabled": $shutdown_disabled,
            "restart_disabled": $restart_disabled,
            "sleep_disabled": $sleep_disabled,
            "custom_message": "$login_text",
            "hide_local_users": $hide_local_users,
            "guest_enabled": $guest_enabled
        },
        "display_mode": "$([ "$show_fullname" == "true" ] && echo "username_dialog" || echo "user_list")",
        "security_level": "unknown",
        "compliance_status": "compliant"
    }
}
EOF
    
    log_action "Rapport de politique généré : $report_file"
}

# Surveiller la configuration de la fenêtre de connexion
monitor_login_window() {
    local detailed="${1:-false}"
    
    echo "=== Moniteur de Configuration de Fenêtre de Connexion ==="
    
    # Vérification de configuration de base
    local show_fullname=$(defaults read /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || echo "false")
    local display_mode=$([ "$show_fullname" == "true" ] && echo "Boîte de Dialogue Nom d'Utilisateur/Mot de Passe" || echo "Liste des Utilisateurs")
    
    echo "Mode d'Affichage : $display_mode"
    
    # Statut des options d'alimentation
    local shutdown_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null)" == "true" ] && echo "Masqué" || echo "Visible")
    local restart_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null)" == "true" ] && echo "Masqué" || echo "Visible")
    local sleep_status=$([ "$(defaults read /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null)" == "true" ] && echo "Masqué" || echo "Visible")
    
    echo "Options d'Alimentation :"
    echo "  Bouton d'Arrêt : $shutdown_status"
    echo "  Bouton de Redémarrage : $restart_status"
    echo "  Bouton de Veille : $sleep_status"
    
    # Message personnalisé
    local custom_message=$(defaults read /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || echo "Aucun")
    echo "Message Personnalisé : $custom_message"
    
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "=== Configuration Détaillée ==="
        
        # Paramètres supplémentaires
        local hide_local=$(defaults read /Library/Preferences/com.apple.loginwindow HideLocalUsers 2>/dev/null || echo "false")
        local hide_mobile=$(defaults read /Library/Preferences/com.apple.loginwindow HideMobileAccounts 2>/dev/null || echo "false")
        local guest_enabled=$(defaults read /Library/Preferences/com.apple.loginwindow GuestEnabled 2>/dev/null || echo "false")
        local admin_info=$(defaults read /Library/Preferences/com.apple.loginwindow AdminHostInfo 2>/dev/null || echo "DSStatus")
        
        echo "Paramètres Avancés :"
        echo "  Masquer Utilisateurs Locaux : $hide_local"
        echo "  Masquer Comptes Mobiles : $hide_mobile"
        echo "  Compte Invité Activé : $guest_enabled"
        echo "  Info Hôte Admin : $admin_info"
        
        # Vérifier l'arrière-plan personnalisé
        local desktop_picture=$(defaults read /Library/Preferences/com.apple.loginwindow DesktopPicture 2>/dev/null || echo "Par Défaut")
        echo "  Image de Bureau : $desktop_picture"
    fi
}

# 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 de Fenêtre de Connexion Roundfleet Démarrée ==="
    log_action "Action : $action"
    
    # Assurer les privilèges requis pour les changements de configuration
    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
        "policy")
            if [[ -z "$param1" ]]; then
                echo "Politiques disponibles : ${!LOGIN_POLICIES[*]}"
                exit 1
            fi
            enforce_login_policy "$param1" "$param2" "$param3" "$param4"
            ;;
        "message")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 message <texte_message>"
                exit 1
            fi
            defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "$param1"
            echo "✓ Message personnalisé défini : $param1"
            ;;
        "power")
            case "$param1" in
                "disable")
                    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
                    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled true
                    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
                    echo "✓ Toutes les options d'alimentation désactivées"
                    ;;
                "enable")
                    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled false
                    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
                    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled false
                    echo "✓ Toutes les options d'alimentation activées"
                    ;;
                *)
                    echo "Usage : $0 power <enable|disable>"
                    exit 1
                    ;;
            esac
            ;;
        "display")
            case "$param1" in
                "userlist")
                    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME false
                    echo "✓ Affichage de la liste des utilisateurs activé"
                    ;;
                "dialog")
                    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
                    echo "✓ Boîte de dialogue nom d'utilisateur/mot de passe activée"
                    ;;
                *)
                    echo "Usage : $0 display <userlist|dialog>"
                    exit 1
                    ;;
            esac
            ;;
        "status")
            monitor_login_window "$param1"
            ;;
        "reset")
            echo "Réinitialisation de la fenêtre de connexion aux paramètres par défaut..."
            defaults delete /Library/Preferences/com.apple.loginwindow SHOWFULLNAME 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow ShutDownDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow RestartDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow SleepDisabled 2>/dev/null || true
            defaults delete /Library/Preferences/com.apple.loginwindow LoginwindowText 2>/dev/null || true
            echo "✓ Fenêtre de connexion réinitialisée aux paramètres système par défaut"
            ;;
        "help")
            echo "Usage : $0 [action] [options...]"
            echo "Actions :"
            echo "  policy <nom_politique> [entreprise] [support] [dry_run] - Appliquer une politique"
            echo "  message <texte> - Définir un message de connexion personnalisé"
            echo "  power <enable|disable> - Contrôler la visibilité des boutons d'alimentation"
            echo "  display <userlist|dialog> - Définir le mode d'affichage utilisateur"
            echo "  status [detailed] - Afficher la configuration actuelle"
            echo "  reset - Réinitialiser aux paramètres système par défaut"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Politiques : ${!LOGIN_POLICIES[*]}"
            echo "Modèles de Messages : ${!MESSAGE_TEMPLATES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion de fenêtre de connexion terminée ==="
}

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

Meilleures Pratiques de Sécurité de Fenêtre de Connexion

Configuration de Sécurité d'Entreprise

#!/bin/bash

# Implémenter la sécurité de fenêtre de connexion d'entreprise
implement_corporate_security() {
    echo "=== Implémentation de la Sécurité de Fenêtre de Connexion d'Entreprise ==="
    
    # Masquer l'énumération des utilisateurs
    defaults write /Library/Preferences/com.apple.loginwindow SHOWFULLNAME true
    
    # Désactiver les options d'alimentation pour prévenir les arrêts non autorisés
    defaults write /Library/Preferences/com.apple.loginwindow ShutDownDisabled true
    defaults write /Library/Preferences/com.apple.loginwindow SleepDisabled true
    
    # Permettre le redémarrage pour les mises à jour (optionnel)
    defaults write /Library/Preferences/com.apple.loginwindow RestartDisabled false
    
    # Définir un message de sécurité d'entreprise
    defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Propriété d'Entreprise - Personnel Autorisé Uniquement"
    
    # Désactiver le compte invité
    defaults write /Library/Preferences/com.apple.loginwindow GuestEnabled false
    
    # Masquer les informations de l'ordinateur
    defaults write /Library/Preferences/com.apple.loginwindow AdminHostInfo ""
    
    echo "✓ Configuration de sécurité d'entreprise appliquée"
}

implement_corporate_security

Notes Importantes

  • Privilèges administrateur requis pour les modifications de la fenêtre de connexion
  • Les changements prennent effet après déconnexion ou redémarrage
  • Tester minutieusement sur des appareils individuels avant le déploiement en flotte
  • Sauvegarder les paramètres avant d'apporter des changements
  • Implications de sécurité - Considérer masquer les listes d'utilisateurs dans les environnements haute sécurité
  • Expérience utilisateur - Équilibrer sécurité et utilisabilité
  • Exigences de conformité - Certaines industries nécessitent des configurations spécifiques de fenêtre de connexion
  • Caractères spéciaux - Éviter les points d'exclamation dans les messages personnalisés à cause de l'interprétation du shell

Gestion d'Entreprise de l'Historique de Connexion sur macOS

Surveillez et analysez l'activité de connexion des utilisateurs sur vos appareils Roundfleet en utilisant des outils en ligne de commande avancés. Ce tutoriel couvre le suivi de l'historique de connexion, l'analyse des sessions utilisateur, l'audit de sécurité, et la surveillance de conformité de niveau entreprise avec des capacités de rapport complètes.

Comprendre la Gestion de l'Historique de Connexion macOS

macOS fournit plusieurs outils puissants pour traquer l'activité de connexion des utilisateurs :

  • who - Affiche les utilisateurs actuellement connectés et un bref historique de connexion
  • last - Affiche l'historique de connexion détaillé avec les informations de session
  • dscl - Utilitaire en ligne de commande des Services d'Annuaire pour la gestion des utilisateurs
  • w - Informations étendues d'activité utilisateur avec la charge système
  • finger - Informations utilisateur et détails de connexion (si disponible)

Ces outils accèdent aux journaux système et aux bases de données utilisateur pour fournir des capacités de suivi de connexion complètes.

Commandes de Base de l'Historique de Connexion

Historique de Connexion Bref avec who

#!/bin/bash

# Afficher l'historique de connexion bref
get_brief_login_history() {
    echo "=== Historique de Connexion Bref ==="
    who
    echo ""
    
    # Alternative avec horodatages
    echo "=== Sessions Utilisateur Actuelles ==="
    who -u
}

# Exécuter la vérification de connexion de base
get_brief_login_history

Historique de Connexion Détaillé avec last

#!/bin/bash

# Afficher l'historique de connexion détaillé
get_detailed_login_history() {
    echo "=== Historique de Connexion Détaillé ==="
    last
    echo ""
    
    # Afficher les 10 dernières entrées de connexion
    echo "=== 10 Dernières Sessions de Connexion ==="
    last -10
    echo ""
    
    # Afficher l'historique de connexion d'aujourd'hui
    echo "=== Sessions de Connexion d'Aujourd'hui ==="
    last -t "$(date '+%Y%m%d%H%M%S')"
}

# Exécuter la vérification de connexion détaillée
get_detailed_login_history

Vérifier l'Historique de Connexion d'un Utilisateur Spécifique

#!/bin/bash

# Obtenir l'heure de dernière connexion pour un utilisateur spécifique
check_user_login() {
    local username="$1"
    
    if [[ -z "$username" ]]; then
        echo "Usage : check_user_login <nom_utilisateur>"
        return 1
    fi
    
    echo "=== Dernière Connexion pour l'Utilisateur : $username ==="
    last -1 "$username"
    echo ""
    
    # Informations utilisateur supplémentaires
    echo "=== Informations du Compte Utilisateur ==="
    dscl . -read "/Users/$username" RealName 2>/dev/null || echo "Utilisateur non trouvé"
    dscl . -read "/Users/$username" UniqueID 2>/dev/null || echo "UID non disponible"
}

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

Analyse Avancée de l'Historique de Connexion

Analyse Complète des Sessions Utilisateur

#!/bin/bash

# Analyse avancée de l'historique de connexion avec insights de sécurité
analyze_login_patterns() {
    echo "=== Analyse Complète de Connexion ==="
    echo "Généré : $(date)"
    echo "Nom d'hôte : $(hostname)"
    echo "=================================="
    echo ""
    
    # Sessions actives actuelles
    echo "1. SESSIONS UTILISATEUR ACTIVES :"
    echo "--------------------------------"
    who -u | while IFS= read -r line; do
        echo "  $line"
    done
    echo ""
    
    # Activité de connexion récente (dernières 24 heures)
    echo "2. ACTIVITÉ DE CONNEXION RÉCENTE (24 heures) :"
    echo "----------------------------------------------"
    local yesterday
    yesterday=$(date -v-1d '+%Y%m%d%H%M%S' 2>/dev/null || date -d 'yesterday' '+%Y%m%d%H%M%S' 2>/dev/null)
    
    if [[ -n "$yesterday" ]]; then
        last -t "$yesterday" | head -20
    else
        last -20
    fi
    echo ""
    
    # Tentatives de connexion échouées (si disponible dans les journaux)
    echo "3. TENTATIVES DE CONNEXION ÉCHOUÉES :"
    echo "------------------------------------"
    grep "authentication failure" /var/log/system.log 2>/dev/null | tail -10 || echo "Aucun échec récent trouvé"
    echo ""
    
    # Analyse de fréquence de connexion
    echo "4. FRÉQUENCE DE CONNEXION PAR UTILISATEUR :"
    echo "------------------------------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    echo ""
    
    # Analyse des connexions distantes vs locales
    echo "5. ANALYSE SOURCE DE CONNEXION :"
    echo "-------------------------------"
    echo "Connexions console :"
    last | grep -c "console" || echo "0"
    echo "Connexions distantes :"
    last | grep -v "console" | grep -v "wtmp begins" | wc -l | tr -d ' '
}

# Exécuter l'analyse complète
analyze_login_patterns

Découverte des Comptes Utilisateur

#!/bin/bash

# Lister tous les utilisateurs et leur statut de connexion
discover_users() {
    echo "=== Découverte des Comptes Utilisateur ==="
    echo ""
    
    # Tous les utilisateurs des services d'annuaire
    echo "1. TOUS LES UTILISATEURS SYSTÈME :"
    echo "---------------------------------"
    dscl . list /Users | grep -v "^_" | grep -v "^root" | grep -v "^daemon" | grep -v "^nobody"
    echo ""
    
    # Utilisateurs avec UID >= 500 (typiquement utilisateurs réguliers)
    echo "2. COMPTES UTILISATEUR RÉGULIERS :"
    echo "---------------------------------"
    dscl . list /Users UniqueID | awk '$2 >= 500 {print $1, "(UID: " $2 ")"}'
    echo ""
    
    # Utilisateurs avec activité de connexion récente
    echo "3. UTILISATEURS AVEC ACTIVITÉ DE CONNEXION RÉCENTE :"
    echo "---------------------------------------------------"
    last | awk '{print $1}' | sort | uniq | grep -v "wtmp" | grep -v "^$" | head -10
    echo ""
    
    # Répertoires personnels
    echo "4. RÉPERTOIRES PERSONNELS UTILISATEUR :"
    echo "---------------------------------------"
    ls -la /Users/ | grep -v "^total" | grep -v "Shared" | awk '{print $9, $3, $4}' | grep -v "^$"
}

# Exécuter la découverte des utilisateurs
discover_users

Système de Gestion de l'Historique de Connexion d'Entreprise

#!/bin/bash

# Système de Gestion de l'Historique de Connexion d'Entreprise Roundfleet
# Surveillance complète de l'activité utilisateur et audit de sécurité

# Configuration
LOG_FILE="/var/log/roundfleet_login_history.log"
REPORT_DIR="/var/reports/roundfleet/login_history"
CONFIG_FILE="/etc/roundfleet/login_monitoring.conf"
ALERT_THRESHOLD_FAILED_LOGINS=5
ALERT_THRESHOLD_UNUSUAL_HOURS=22  # Alerte pour connexions après 22h

# Créer la structure des répertoires
setup_directories() {
    mkdir -p "$(dirname "$LOG_FILE")" "$REPORT_DIR" "$(dirname "$CONFIG_FILE")"
    touch "$LOG_FILE"
}

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

# Générer un rapport de connexion complet
generate_login_report() {
    local report_file="$REPORT_DIR/login_report_$(date +%Y%m%d_%H%M%S).json"
    
    log_action "Génération du rapport d'historique de connexion complet : $report_file"
    
    {
        echo "{"
        echo "  \"report_type\": \"login_history\","
        echo "  \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\","
        echo "  \"hostname\": \"$(hostname)\","
        echo "  \"system_info\": {"
        echo "    \"macos_version\": \"$(sw_vers -productVersion)\","
        echo "    \"uptime\": \"$(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')\","
        echo "    \"current_users\": $(who | wc -l | tr -d ' ')"
        echo "  },"
        
        # Sessions actives
        echo "  \"active_sessions\": ["
        local first_session=true
        who -u | while IFS= read -r line; do
            if [[ "$first_session" == "false" ]]; then
                echo ","
            fi
            first_session=false
            
            local user terminal login_time pid
            user=$(echo "$line" | awk '{print $1}')
            terminal=$(echo "$line" | awk '{print $2}')
            login_time=$(echo "$line" | awk '{print $3, $4}')
            pid=$(echo "$line" | awk '{print $6}')
            
            echo "    {"
            echo "      \"user\": \"$user\","
            echo "      \"terminal\": \"$terminal\","
            echo "      \"login_time\": \"$login_time\","
            echo "      \"pid\": \"$pid\""
            echo -n "    }"
        done
        echo ""
        echo "  ],"
        
        # Historique de connexion récent
        echo "  \"recent_logins\": ["
        local first_login=true
        last -20 | grep -v "wtmp begins" | while IFS= read -r line; do
            if [[ -n "$line" ]]; then
                if [[ "$first_login" == "false" ]]; then
                    echo ","
                fi
                first_login=false
                
                local user terminal source login_date login_time logout_info
                user=$(echo "$line" | awk '{print $1}')
                terminal=$(echo "$line" | awk '{print $2}')
                source=$(echo "$line" | awk '{print $3}')
                login_date=$(echo "$line" | awk '{print $4, $5, $6}')
                login_time=$(echo "$line" | awk '{print $7}')
                logout_info=$(echo "$line" | awk '{print $9, $10}')
                
                echo "    {"
                echo "      \"user\": \"$user\","
                echo "      \"terminal\": \"$terminal\","
                echo "      \"source\": \"$source\","
                echo "      \"login_date\": \"$login_date\","
                echo "      \"login_time\": \"$login_time\","
                echo "      \"logout_info\": \"$logout_info\""
                echo -n "    }"
            fi
        done
        echo ""
        echo "  ],"
        
        # Statistiques utilisateur
        echo "  \"user_statistics\": {"
        local total_users
        total_users=$(dscl . list /Users | grep -v "^_" | wc -l | tr -d ' ')
        echo "    \"total_system_users\": $total_users,"
        
        local regular_users
        regular_users=$(dscl . list /Users UniqueID | awk '$2 >= 500' | wc -l | tr -d ' ')
        echo "    \"regular_users\": $regular_users,"
        
        local active_login_users
        active_login_users=$(last | awk '{print $1}' | sort | uniq | grep -v "wtmp" | grep -v "^$" | wc -l | tr -d ' ')
        echo "    \"users_with_login_history\": $active_login_users"
        echo "  }"
        echo "}"
    } > "$report_file"
    
    log_action "Rapport d'historique de connexion généré avec succès"
    echo "$report_file"
}

# Surveiller l'activité de connexion suspecte
monitor_suspicious_activity() {
    log_action "Démarrage de la surveillance d'activité de connexion suspecte..."
    
    local alerts=()
    
    # Vérifier les heures de connexion inhabituelles (configurable)
    local current_hour
    current_hour=$(date +%H)
    
    if [[ "$current_hour" -ge "$ALERT_THRESHOLD_UNUSUAL_HOURS" ]]; then
        local late_logins
        late_logins=$(who | wc -l | tr -d ' ')
        
        if [[ "$late_logins" -gt 0 ]]; then
            alerts+=("Activité de connexion nocturne détectée : $late_logins sessions actives après $ALERT_THRESHOLD_UNUSUAL_HOURS:00")
        fi
    fi
    
    # Vérifier les tentatives de connexion échouées multiples
    local failed_logins
    failed_logins=$(grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | wc -l | tr -d ' ')
    
    if [[ "$failed_logins" -ge "$ALERT_THRESHOLD_FAILED_LOGINS" ]]; then
        alerts+=("Nombre élevé de tentatives de connexion échouées aujourd'hui : $failed_logins échecs")
    fi
    
    # Vérifier les connexions root
    local root_logins
    root_logins=$(last | grep "^root " | head -5 | wc -l | tr -d ' ')
    
    if [[ "$root_logins" -gt 0 ]]; then
        alerts+=("Activité de connexion root récente détectée : $root_logins sessions")
    fi
    
    # Vérifier les connexions simultanées du même utilisateur
    local duplicate_users
    duplicate_users=$(who | awk '{print $1}' | sort | uniq -d)
    
    if [[ -n "$duplicate_users" ]]; then
        alerts+=("Sessions simultanées multiples détectées pour les utilisateurs : $duplicate_users")
    fi
    
    # Rapporter les alertes
    if [[ ${#alerts[@]} -eq 0 ]]; then
        log_action "✅ Aucune activité de connexion suspecte détectée"
        return 0
    else
        log_action "⚠️  Alertes d'activité de connexion suspecte :"
        for alert in "${alerts[@]}"; do
            log_action "  - $alert"
        done
        return 1
    fi
}

# Analyser les modèles de connexion pour insights de sécurité
analyze_security_patterns() {
    log_action "Analyse des modèles de connexion pour insights de sécurité..."
    
    echo "=== Analyse des Modèles de Sécurité ==="
    echo ""
    
    # Fréquence de connexion par jour de la semaine
    echo "1. FRÉQUENCE DE CONNEXION PAR JOUR :"
    echo "-----------------------------------"
    last | grep -v "wtmp begins" | awk '{print $4}' | sort | uniq -c | sort -nr
    echo ""
    
    # Utilisateurs les plus actifs
    echo "2. UTILISATEURS LES PLUS ACTIFS :"
    echo "--------------------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
    echo ""
    
    # Analyse des sources de connexion
    echo "3. SOURCES DE CONNEXION :"
    echo "------------------------"
    echo "Connexions console : $(last | grep -c "console")"
    echo "Connexions distantes : $(last | grep -v "console" | grep -v "wtmp begins" | wc -l | tr -d ' ')"
    echo ""
    
    # Analyse de durée de session
    echo "4. MODÈLES DE SESSION :"
    echo "----------------------"
    local avg_sessions
    avg_sessions=$(last | grep -v "wtmp begins" | grep -v "still logged in" | wc -l | tr -d ' ')
    echo "Total sessions terminées : $avg_sessions"
    
    local active_sessions
    active_sessions=$(who | wc -l | tr -d ' ')
    echo "Sessions actuellement actives : $active_sessions"
    echo ""
    
    # Analyse basée sur l'heure
    echo "5. MODÈLES D'HEURE DE CONNEXION :"
    echo "--------------------------------"
    echo "Heures de bureau (9-17) : $(last | awk '{print $7}' | grep -E '^(09|1[0-7]):' | wc -l | tr -d ' ')"
    echo "Après les heures (18-08) : $(last | awk '{print $7}' | grep -E '^(1[8-9]|2[0-3]|0[0-8]):' | wc -l | tr -d ' ')"
}

# Audit d'accès utilisateur
perform_user_audit() {
    local audit_file="$REPORT_DIR/user_audit_$(date +%Y%m%d_%H%M%S).txt"
    
    log_action "Exécution d'un audit d'accès utilisateur complet : $audit_file"
    
    {
        echo "Rapport d'Audit d'Accès Utilisateur Roundfleet"
        echo "Généré : $(date)"
        echo "Nom d'hôte : $(hostname)"
        echo "============================================="
        echo ""
        
        echo "APERÇU SYSTÈME :"
        echo "----------------"
        echo "Version macOS : $(sw_vers -productVersion)"
        echo "Build : $(sw_vers -buildVersion)"
        echo "Temps de fonctionnement système : $(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')"
        echo "Date/Heure actuelle : $(date)"
        echo ""
        
        echo "RÉSUMÉ COMPTES UTILISATEUR :"
        echo "---------------------------"
        echo "Total utilisateurs système : $(dscl . list /Users | wc -l | tr -d ' ')"
        echo "Utilisateurs réguliers (UID >= 500) : $(dscl . list /Users UniqueID | awk '$2 >= 500' | wc -l | tr -d ' ')"
        echo "Actuellement connectés : $(who | wc -l | tr -d ' ')"
        echo ""
        
        echo "INFORMATIONS UTILISATEUR DÉTAILLÉES :"
        echo "------------------------------------"
        dscl . list /Users UniqueID | awk '$2 >= 500' | while read -r username uid; do
            echo "Utilisateur : $username (UID : $uid)"
            
            # Nom réel
            local real_name
            real_name=$(dscl . -read "/Users/$username" RealName 2>/dev/null | grep "RealName:" | cut -d' ' -f2-)
            echo "  Nom réel : ${real_name:-"Non défini"}"
            
            # Répertoire personnel
            local home_dir
            home_dir=$(dscl . -read "/Users/$username" NFSHomeDirectory 2>/dev/null | grep "NFSHomeDirectory:" | cut -d' ' -f2)
            echo "  Répertoire personnel : ${home_dir:-"Non défini"}"
            
            # Dernière connexion
            local last_login
            last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $4, $5, $6, $7}')
            echo "  Dernière connexion : ${last_login:-"Jamais"}"
            
            # Statut du compte
            local account_disabled
            account_disabled=$(dscl . -read "/Users/$username" AuthenticationAuthority 2>/dev/null | grep -c "DisabledUser" || echo "0")
            if [[ "$account_disabled" -gt 0 ]]; then
                echo "  Statut : DÉSACTIVÉ"
            else
                echo "  Statut : Actif"
            fi
            
            echo ""
        done
        
        echo "ACTIVITÉ DE CONNEXION RÉCENTE :"
        echo "------------------------------"
        last -50
        
        echo ""
        echo "RECOMMANDATIONS DE SÉCURITÉ :"
        echo "----------------------------"
        
        # Vérifier les utilisateurs sans activité de connexion récente
        local inactive_users
        inactive_users=$(dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}' | while read -r user; do
            if ! last "$user" | grep -q "$(date '+%b')" 2>/dev/null; then
                echo "$user"
            fi
        done)
        
        if [[ -n "$inactive_users" ]]; then
            echo "• Considérer la révision des comptes utilisateur inactifs :"
            echo "$inactive_users" | while read -r user; do
                echo "  - $user"
            done
        else
            echo "• Tous les utilisateurs ont une activité de connexion récente"
        fi
        
        # Vérifier les utilisateurs admin
        local admin_users
        admin_users=$(dscl . -read /Groups/admin GroupMembership 2>/dev/null | cut -d' ' -f2-)
        if [[ -n "$admin_users" ]]; then
            echo "• Réviser régulièrement l'accès utilisateur admin :"
            for admin in $admin_users; do
                echo "  - $admin"
            done
        fi
        
    } > "$audit_file"
    
    log_action "Audit d'accès utilisateur terminé avec succès"
    echo "$audit_file"
}

# Exporter les données de connexion pour analyse externe
export_login_data() {
    local export_format="${1:-json}"  # json, csv, xml
    local export_file="$REPORT_DIR/login_export_$(date +%Y%m%d_%H%M%S).$export_format"
    
    log_action "Exportation des données de connexion au format $export_format : $export_file"
    
    case "$export_format" in
        "csv")
            {
                echo "Utilisateur,Terminal,Source,DateConnexion,HeureConnexion,InfoDeconnexion,Duree"
                last -100 | grep -v "wtmp begins" | while IFS= read -r line; do
                    if [[ -n "$line" ]]; then
                        echo "$line" | awk -F' ' '{
                            user=$1; terminal=$2; source=$3; 
                            login_date=$4" "$5" "$6; login_time=$7; 
                            logout_info=$9" "$10; duration=$8;
                            print user","terminal","source","login_date","login_time","logout_info","duration
                        }'
                    fi
                done
            } > "$export_file"
            ;;
        "json")
            generate_login_report > /dev/null
            cp "$REPORT_DIR"/login_report_*.json "$export_file" 2>/dev/null || echo "{\"error\": \"Aucun rapport récent trouvé\"}" > "$export_file"
            ;;
        "xml")
            {
                echo '<?xml version="1.0" encoding="UTF-8"?>'
                echo '<login_history>'
                echo "  <generated>$(date -u +%Y-%m-%dT%H:%M:%SZ)</generated>"
                echo "  <hostname>$(hostname)</hostname>"
                echo "  <sessions>"
                
                last -50 | grep -v "wtmp begins" | while IFS= read -r line; do
                    if [[ -n "$line" ]]; then
                        local user terminal source login_date login_time
                        user=$(echo "$line" | awk '{print $1}')
                        terminal=$(echo "$line" | awk '{print $2}')
                        source=$(echo "$line" | awk '{print $3}')
                        login_date=$(echo "$line" | awk '{print $4, $5, $6}')
                        login_time=$(echo "$line" | awk '{print $7}')
                        
                        echo "    <session>"
                        echo "      <user>$user</user>"
                        echo "      <terminal>$terminal</terminal>"
                        echo "      <source>$source</source>"
                        echo "      <login_date>$login_date</login_date>"
                        echo "      <login_time>$login_time</login_time>"
                        echo "    </session>"
                    fi
                done
                
                echo "  </sessions>"
                echo '</login_history>'
            } > "$export_file"
            ;;
        *)
            log_action "ERREUR : Format d'exportation non supporté : $export_format"
            return 1
            ;;
    esac
    
    log_action "Données de connexion exportées avec succès"
    echo "$export_file"
}

# Fonction de gestion principale
main() {
    local action="${1:-report}"
    local parameter="$2"
    
    setup_directories
    log_action "Gestion Historique de Connexion Roundfleet démarrée avec l'action : $action"
    
    case "$action" in
        "brief")
            who
            ;;
        "detailed")
            last
            ;;
        "user")
            if [[ -n "$parameter" ]]; then
                last -1 "$parameter"
            else
                echo "Usage : $0 user <nom_utilisateur>"
                exit 1
            fi
            ;;
        "users")
            dscl . list /Users | grep -v "^_"
            ;;
        "analyze")
            analyze_security_patterns
            ;;
        "monitor")
            monitor_suspicious_activity
            ;;
        "audit")
            perform_user_audit
            ;;
        "export")
            export_login_data "$parameter"
            ;;
        "report"|*)
            generate_login_report
            ;;
    esac
    
    log_action "Gestion Historique de Connexion Roundfleet terminée avec l'action : $action"
}

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

Fonctions de Gestion Rapide

Vérification Simple du Statut de Connexion

#!/bin/bash

# Statut de connexion rapide avec sortie améliorée
quick_login_status() {
    echo "📊 Statut de Connexion Roundfleet - $(date)"
    echo "=========================================="
    
    # Utilisateurs actuels
    local current_users
    current_users=$(who | wc -l | tr -d ' ')
    echo "👥 Actuellement connectés : $current_users utilisateurs"
    
    if [[ "$current_users" -gt 0 ]]; then
        echo ""
        echo "Sessions Actives :"
        who | while IFS= read -r line; do
            echo "  🔹 $line"
        done
    fi
    
    echo ""
    echo "📈 Activité Récente :"
    echo "  - Dernières 24 heures : $(last -t "$(date -v-1d '+%Y%m%d%H%M%S' 2>/dev/null || date -d 'yesterday' '+%Y%m%d%H%M%S')" | wc -l | tr -d ' ') connexions"
    echo "  - Cette semaine : $(last | grep "$(date '+%b')" | wc -l | tr -d ' ') connexions"
    
    # Temps de fonctionnement système
    echo "  - Temps de fonctionnement système : $(uptime | awk -F'up ' '{print $2}' | awk -F', ' '{print $1}')"
}

quick_login_status

Résumé de Connexion Utilisateur

#!/bin/bash

# Générer un résumé de connexion utilisateur
user_login_summary() {
    echo "🔍 Résumé de Connexion Utilisateur"
    echo "=================================="
    echo ""
    
    echo "Top 10 Utilisateurs les Plus Actifs :"
    echo "-------------------------------------"
    last | grep -v "wtmp begins" | awk '{print $1}' | sort | uniq -c | sort -nr | head -10 | while read -r count user; do
        echo "  $user : $count connexions"
    done
    
    echo ""
    echo "Activité Utilisateur Récente :"
    echo "-----------------------------"
    dscl . list /Users UniqueID | awk '$2 >= 500 {print $1}' | head -10 | while read -r username; do
        local last_login
        last_login=$(last -1 "$username" 2>/dev/null | head -1 | awk '{print $4, $5, $7}' | tr -s ' ')
        echo "  $username : ${last_login:-"Aucune activité récente"}"
    done
}

user_login_summary

Fonctions de Surveillance de Sécurité

Détection de Connexions Échouées

#!/bin/bash

# Surveiller et rapporter les tentatives de connexion échouées
monitor_failed_logins() {
    echo "🔒 Surveillance des Connexions Échouées"
    echo "======================================="
    echo ""
    
    # Vérifier le journal système pour les échecs d'authentification
    echo "Tentatives de Connexion Échouées Récentes :"
    echo "------------------------------------------"
    
    # Dernières 24 heures de tentatives échouées
    grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | while IFS= read -r line; do
        echo "  ⚠️  $line"
    done || echo "  ✅ Aucune tentative de connexion échouée trouvée aujourd'hui"
    
    echo ""
    echo "Résumé des Connexions Échouées :"
    echo "-------------------------------"
    
    # Compter les échecs par utilisateur (si disponible)
    local failure_count
    failure_count=$(grep "authentication failure" /var/log/system.log 2>/dev/null | grep "$(date '+%b %d')" | wc -l | tr -d ' ')
    echo "  Total d'échecs aujourd'hui : $failure_count"
    
    # Recommandations
    if [[ "$failure_count" -gt 5 ]]; then
        echo ""
        echo "🚨 Alerte de Sécurité : Nombre élevé de connexions échouées détecté !"
        echo "  - Réviser les comptes utilisateur pour d'éventuelles attaques par force brute"
        echo "  - Considérer l'implémentation de politiques de verrouillage de compte"
        echo "  - Vérifier les adresses IP suspectes dans les journaux"
    fi
}

monitor_failed_logins

Analyse de Durée de Session

#!/bin/bash

# Analyser les durées de session utilisateur
analyze_session_duration() {
    echo "⏱️  Analyse de Durée de Session"
    echo "==============================="
    echo ""
    
    echo "Statistiques de Session :"
    echo "------------------------"
    
    # Sessions actives
    local active_count
    active_count=$(who | wc -l | tr -d ' ')
    echo "  Sessions actives : $active_count"
    
    # Analyse des sessions terminées
    echo "  Sessions terminées récentes :"
    last | grep -v "still logged in" | grep -v "wtmp begins" | head -10 | while IFS= read -r line; do
        local duration
        duration=$(echo "$line" | awk '{print $10}' | tr -d '()')
        if [[ -n "$duration" ]]; then
            echo "    Durée : $duration"
        fi
    done
    
    echo ""
    echo "Sessions de Longue Durée (Actives) :"
    echo "-----------------------------------"
    who -u | while IFS= read -r line; do
        local login_time pid idle
        login_time=$(echo "$line" | awk '{print $3, $4}')
        pid=$(echo "$line" | awk '{print $6}')
        idle=$(echo "$line" | awk '{print $5}')
        
        if [[ "$idle" != "." ]]; then
            echo "  Session démarrée : $login_time (Inactif : $idle)"
        else
            echo "  Session démarrée : $login_time (Actif)"
        fi
    done
}

analyze_session_duration

Configuration et Conformité

Configuration de Politique de Connexion

# /etc/roundfleet/login_monitoring.conf
# Configuration de Surveillance d'Historique de Connexion Roundfleet

# Seuils d'alerte
ALERT_THRESHOLD_FAILED_LOGINS=5
ALERT_THRESHOLD_UNUSUAL_HOURS=22
ALERT_THRESHOLD_SIMULTANEOUS_SESSIONS=3

# Paramètres de surveillance
MONITOR_INTERVAL_MINUTES=15
LOG_RETENTION_DAYS=90
REPORT_GENERATION_SCHEDULE="daily"

# Politiques de sécurité
REQUIRE_LOGIN_AUDIT_TRAIL=true
ALERT_ON_ROOT_LOGIN=true
ALERT_ON_AFTER_HOURS_LOGIN=true
MONITOR_REMOTE_LOGINS=true

# Paramètres de conformité
GDPR_COMPLIANCE=true
SOX_COMPLIANCE=false
HIPAA_COMPLIANCE=false
EXPORT_FORMAT="json"  # json, csv, xml

Rapport de Conformité

#!/bin/bash

# Générer des rapports de connexion prêts pour la conformité
generate_compliance_report() {
    local compliance_type="${1:-general}"
    local report_file="$REPORT_DIR/compliance_${compliance_type}_$(date +%Y%m%d).txt"
    
    echo "📋 Génération du rapport de conformité $compliance_type..."
    
    {
        echo "RAPPORT DE CONFORMITÉ HISTORIQUE DE CONNEXION"
        echo "============================================="
        echo "Type de rapport : $compliance_type"
        echo "Généré : $(date)"
        echo "Période : $(date -v-30d '+%Y-%m-%d') à $(date '+%Y-%m-%d')"
        echo "Système : $(hostname)"
        echo ""
        
        case "$compliance_type" in
            "gdpr")
                echo "ENREGISTREMENT DE TRAITEMENT DES DONNÉES RGPD :"
                echo "----------------------------------------------"
                echo "• Données de connexion collectées pour surveillance de sécurité"
                echo "• Rétention des données : 90 jours (configurable)"
                echo "• Contrôles d'accès : Utilisateurs admin uniquement"
                echo "• Sujets des données : Tous les utilisateurs système"
                echo ""
                ;;
            "sox")
                echo "CONFORMITÉ CONTRÔLE D'ACCÈS SOX :"
                echo "--------------------------------"
                echo "• Surveillance d'accès utilisateur : Activé"
                echo "• Suivi d'accès privilégié : Activé"
                echo "• Surveillance de connexions échouées : Activé"
                echo "• Complétude piste d'audit : Vérifiée"
                echo ""
                ;;
            "hipaa")
                echo "EXIGENCES D'AUDIT D'ACCÈS HIPAA :"
                echo "--------------------------------"
                echo "• Journalisation d'authentification utilisateur : Active"
                echo "• Surveillance tentatives d'accès : Activé"
                echo "• Accès minimum nécessaire : En cours de révision"
                echo "• Intégrité journal d'audit : Maintenue"
                echo ""
                ;;
        esac
        
        echo "ACTIVITÉ DE CONNEXION DÉTAILLÉE :"
        echo "--------------------------------"
        last -30
        
        echo ""
        echo "RÉSUMÉ D'ACCÈS UTILISATEUR :"
        echo "---------------------------"
        dscl . list /Users UniqueID | awk '$2 >= 500' | while read -r username uid; do
            local login_count
            login_count=$(last "$username" | grep -v "wtmp begins" | wc -l | tr -d ' ')
            echo "$username (UID : $uid) : $login_count sessions de connexion"
        done
        
    } > "$report_file"
    
    echo "✅ Rapport de conformité généré : $report_file"
}

# Générer différents rapports de conformité
# generate_compliance_report "gdpr"
# generate_compliance_report "sox"
# generate_compliance_report "hipaa"

Notes Techniques Importantes

Détails des Commandes

  • who : Affiche les utilisateurs actuellement connectés avec heures de connexion
  • last : Affiche l'historique de connexion depuis /var/log/wtmp
  • dscl : Ligne de commande Services d'Annuaire pour informations utilisateur
  • w : Version étendue de who avec informations de charge système

Emplacements des Fichiers de Journal

  • /var/log/wtmp : Base de données binaire d'historique de connexion
  • /var/log/system.log : Journal système incluant événements d'authentification
  • /var/log/secure.log : Entrées de journal liées à la sécurité (si activé)

Considérations de Sécurité

  1. Conformité Confidentialité : La surveillance de connexion doit respecter les lois locales de confidentialité
  2. Rétention de Données : Implémenter des politiques de rétention appropriées pour les journaux d'audit
  3. Contrôle d'Accès : Restreindre l'accès aux données d'historique de connexion au personnel autorisé
  4. Surveillance Temps Réel : Considérer l'implémentation d'alertes temps réel pour activité suspecte

Meilleures Pratiques

  1. Audit Régulier : Réviser les modèles de connexion régulièrement pour anomalies
  2. Surveillance Automatisée : Configurer des alertes automatisées pour activité suspecte
  3. Rétention de Données : Maintenir une rétention de journal appropriée pour exigences de conformité
  4. Confidentialité Utilisateur : Équilibrer surveillance de sécurité avec attentes de confidentialité utilisateur
  5. Documentation : Maintenir une documentation claire des procédures de surveillance
  6. Intégration : Considérer l'intégration avec systèmes SIEM pour surveillance centralisée
  7. Impact Performance : Surveiller l'impact sur performance système des activités de journalisation
  8. Stratégie Sauvegarde : Implémenter procédures de sauvegarde pour journaux d'audit critiques

N'oubliez pas de valider tous les scripts sur des appareils de test avant de les déployer sur votre environnement Roundfleet, et assurez-vous de la conformité avec les politiques de confidentialité et de sécurité de votre organisation lors de l'implémentation de la surveillance d'historique de connexion.

Gérer les Services de Localisation sur macOS

Contrôlez les Services de Localisation sur vos appareils Roundfleet en utilisant des outils en ligne de commande. Ce tutoriel couvre l'activation, la désactivation et la surveillance des services de localisation pour une meilleure gestion de la confidentialité et conformité de sécurité.

Comprendre les Services de Localisation macOS

Les Services de Localisation permettent aux applications et services macOS de collecter des informations basées sur la localisation pour améliorer l'expérience utilisateur. Cependant, l'activation de ces services peut créer des préoccupations potentielles de sécurité et de confidentialité.

Considérations clés :

  • Fonctionnalités améliorées - Les applications comme Plans nécessitent l'accès à la localisation
  • Préoccupations de confidentialité - Potentiel de suivi et de collecte de données
  • Risques de sécurité - Surface d'attaque accrue pour les acteurs malveillants
  • Exigences de conformité - Les politiques d'entreprise peuvent nécessiter des restrictions de localisation

Activer les Services de Localisation

Activation Basique des Services de Localisation

#!/bin/bash

# Activer les Services de Localisation à l'échelle du système
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

echo "Services de Localisation activés avec succès"
echo "⚠️  Redémarrage de l'appareil requis pour que les changements prennent effet"

Activer avec Redémarrage Automatique

#!/bin/bash

# Activer les Services de Localisation et programmer un redémarrage
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

echo "Configuration des Services de Localisation mise à jour"
echo "Programmation du redémarrage système dans 60 secondes..."

# Donner aux utilisateurs le temps de sauvegarder leur travail
sleep 60
sudo reboot

Vérifier le Succès de l'Activation

#!/bin/bash

# Activer les Services de Localisation avec vérification
echo "Activation des Services de Localisation..."
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true

# Vérifier si le paramètre a été appliqué
if sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" LocationServicesEnabled 2>/dev/null; then
    echo "✅ Configuration des Services de Localisation mise à jour avec succès"
    echo "🔄 Redémarrage requis pour appliquer les changements"
else
    echo "❌ Échec de la mise à jour de la configuration des Services de Localisation"
    exit 1
fi

Désactiver les Services de Localisation

Désactivation Basique des Services de Localisation

#!/bin/bash

# Désactiver les Services de Localisation à l'échelle du système
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

echo "Services de Localisation désactivés avec succès"
echo "⚠️  Redémarrage de l'appareil requis pour que les changements prennent effet"

Désactiver avec Notification de Confidentialité

#!/bin/bash

# Désactiver les Services de Localisation avec notification utilisateur
echo "🔒 Mise en place des mesures de protection de la confidentialité..."
echo "Désactivation des Services de Localisation pour une sécurité renforcée"

sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

echo "✅ Les Services de Localisation ont été désactivés"
echo "🔄 Redémarrage système requis pour compléter le processus"
echo "📱 Les applications n'auront plus accès aux données de localisation"

Désactivation Sécurisée d'Entreprise

#!/bin/bash

# Désactivation des services de localisation de niveau entreprise avec journalisation
LOG_FILE="/var/log/roundfleet_location_services.log"

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

log_action "=== Désactivation Sécurisée des Services de Localisation Initiée ==="

# Vérifier le statut actuel
CURRENT_STATUS=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" LocationServicesEnabled 2>/dev/null)

if [[ "$CURRENT_STATUS" == "1" ]]; then
    log_action "Services de Localisation actuellement activés - procédure de désactivation"
    
    # Désactiver les services de localisation
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false
    
    log_action "Services de Localisation désactivés pour conformité de sécurité"
    log_action "Redémarrage système requis pour compléter le durcissement de sécurité"
    
    echo "🔒 Politique de sécurité appliquée : Services de Localisation désactivés"
    echo "📋 Action journalisée dans : $LOG_FILE"
else
    log_action "Services de Localisation déjà désactivés - aucune action requise"
    echo "✅ Services de Localisation déjà sécurisés"
fi

Vérifier le Statut des Services de Localisation

Vérification Basique du Statut

#!/bin/bash

# Vérifier le statut actuel des Services de Localisation
sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd"

echo "Statut des Services de Localisation récupéré"

Rapport de Statut Détaillé

#!/bin/bash

# Vérification complète du statut des Services de Localisation
echo "=== Rapport de Statut des Services de Localisation ==="
echo "Appareil : $(hostname)"
echo "Date : $(date)"
echo "========================================"

# Vérifier si le daemon locationd fonctionne
if pgrep -x "locationd" > /dev/null; then
    echo "📍 Daemon de localisation : En cours d'exécution"
else
    echo "❌ Daemon de localisation : Non en cours d'exécution"
fi

# Obtenir la configuration actuelle
STATUS_OUTPUT=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" 2>&1)

if echo "$STATUS_OUTPUT" | grep -q "LocationServicesEnabled = 1"; then
    echo "🟢 Services de Localisation : ACTIVÉS"
    echo "📱 Les applications peuvent accéder aux données de localisation"
elif echo "$STATUS_OUTPUT" | grep -q "LocationServicesEnabled = 0"; then
    echo "🔴 Services de Localisation : DÉSACTIVÉS"
    echo "🔒 Accès à la localisation bloqué pour toutes les applications"
else
    echo "⚠️  Services de Localisation : Statut incertain"
    echo "Sortie brute : $STATUS_OUTPUT"
fi

echo "========================================"

Surveillance de Statut à l'Échelle de la Flotte

#!/bin/bash

# Script de Surveillance des Services de Localisation Roundfleet
LOG_FILE="/var/log/roundfleet_location_monitoring.log"
REPORT_FILE="/tmp/location_services_report.txt"

# Créer un rapport de statut
generate_report() {
    {
        echo "Rapport des Services de Localisation Roundfleet"
        echo "Généré : $(date)"
        echo "Appareil : $(hostname)"
        echo "Utilisateur : $(whoami)"
        echo "================================"
        echo ""
        
        # Informations système
        echo "Informations Système :"
        echo "Version OS : $(sw_vers -productVersion)"
        echo "Build : $(sw_vers -buildVersion)"
        echo ""
        
        # Statut du daemon de localisation
        echo "Statut du Daemon de Localisation :"
        if pgrep -x "locationd" > /dev/null; then
            echo "Statut : En cours d'exécution (PID : $(pgrep -x "locationd"))"
        else
            echo "Statut : Non en cours d'exécution"
        fi
        echo ""
        
        # Statut de configuration
        echo "Configuration des Services de Localisation :"
        local status_output
        status_output=$(sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd" 2>&1)
        
        if echo "$status_output" | grep -q "LocationServicesEnabled = 1"; then
            echo "Statut : ACTIVÉ"
            echo "Niveau de Confidentialité : Standard"
        elif echo "$status_output" | grep -q "LocationServicesEnabled = 0"; then
            echo "Statut : DÉSACTIVÉ"
            echo "Niveau de Confidentialité : Élevé"
        else
            echo "Statut : Inconnu"
            echo "Configuration Brute :"
            echo "$status_output"
        fi
        
        echo ""
        echo "Rapport terminé à : $(date)"
        
    } > "$REPORT_FILE"
    
    echo "📊 Rapport généré : $REPORT_FILE"
}

# Journaliser l'action de surveillance
echo "$(date '+%Y-%m-%d %H:%M:%S') - Surveillance des Services de Localisation initiée" >> "$LOG_FILE"

# Générer le rapport
generate_report

# Afficher le résumé
echo "=== Résumé des Services de Localisation Roundfleet ==="
cat "$REPORT_FILE"

Gestion Avancée de la Localisation

Contrôle Conditionnel de la Localisation

#!/bin/bash

# Gestion intelligente des services de localisation basée sur l'environnement
NETWORK_SSID=$(networksetup -getairportnetwork en0 | cut -d' ' -f4-)
LOCATION_POLICY=""

# Définir les politiques de localisation basées sur le réseau
case "$NETWORK_SSID" in
    "Corporate_WiFi"|"Company_Network")
        LOCATION_POLICY="disable"
        echo "🏢 Réseau d'entreprise détecté - application de la politique de sécurité"
        ;;
    "Home_Network"|"Personal_WiFi")
        LOCATION_POLICY="enable"
        echo "🏠 Réseau personnel détecté - autorisation des services de localisation"
        ;;
    *)
        LOCATION_POLICY="disable"
        echo "🔒 Réseau inconnu - application de la politique restrictive"
        ;;
esac

# Appliquer la politique
if [[ "$LOCATION_POLICY" == "disable" ]]; then
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false
    echo "🔴 Services de Localisation désactivés pour la sécurité"
else
    sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool true
    echo "🟢 Services de Localisation activés"
fi

echo "⚠️  Redémarrage requis pour que les changements prennent effet"

Sauvegarde et Restauration des Services de Localisation

#!/bin/bash

# Sauvegarde et restauration de la configuration des services de localisation
BACKUP_DIR="/var/backups/roundfleet"
BACKUP_FILE="$BACKUP_DIR/location_services_$(date +%Y%m%d_%H%M%S).plist"

# Créer le répertoire de sauvegarde
sudo mkdir -p "$BACKUP_DIR"

backup_settings() {
    echo "📦 Sauvegarde de la configuration des Services de Localisation..."
    
    if sudo cp "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist" "$BACKUP_FILE" 2>/dev/null; then
        echo "✅ Sauvegarde enregistrée dans : $BACKUP_FILE"
    else
        echo "❌ Échec de la sauvegarde - le fichier de configuration pourrait ne pas exister"
        return 1
    fi
}

restore_settings() {
    local restore_file="$1"
    
    if [[ -z "$restore_file" ]]; then
        echo "Usage : restore_settings <fichier_sauvegarde>"
        return 1
    fi
    
    if [[ ! -f "$restore_file" ]]; then
        echo "❌ Fichier de sauvegarde non trouvé : $restore_file"
        return 1
    fi
    
    echo "🔄 Restauration de la configuration des Services de Localisation..."
    
    if sudo cp "$restore_file" "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist"; then
        echo "✅ Configuration restaurée avec succès"
        echo "🔄 Redémarrage requis pour appliquer les changements"
    else
        echo "❌ Échec de la restauration"
        return 1
    fi
}

# Exécuter la sauvegarde
backup_settings

Considérations de Sécurité

Durcissement de Sécurité d'Entreprise

#!/bin/bash

# Durcissement complet de sécurité des services de localisation
echo "🔒 Durcissement de Sécurité Roundfleet : Services de Localisation"
echo "=============================================================="

# 1. Désactiver les services de localisation
echo "Étape 1 : Désactivation des Services de Localisation..."
sudo /usr/bin/defaults write /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd LocationServicesEnabled -bool false

# 2. Vérifier la configuration du daemon
echo "Étape 2 : Vérification de la configuration du daemon..."
if pgrep -x "locationd" > /dev/null; then
    echo "⚠️  Le daemon de localisation fonctionne encore (s'arrêtera après redémarrage)"
else
    echo "✅ Le daemon de localisation ne fonctionne pas"
fi

# 3. Définir les permissions de fichier
echo "Étape 3 : Sécurisation des fichiers de configuration..."
sudo chmod 600 /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist 2>/dev/null
sudo chown _locationd:_locationd /var/db/locationd/Library/Preferences/ByHost/com.apple.locationd.plist 2>/dev/null

# 4. Créer un rapport de sécurité
SECURITY_REPORT="/var/log/roundfleet_location_security.log"
{
    echo "Rapport de Durcissement de Sécurité des Services de Localisation Roundfleet"
    echo "Date : $(date)"
    echo "Appareil : $(hostname)"
    echo "Action : Services de Localisation Désactivés"
    echo "Conformité : Protection de Confidentialité Renforcée"
    echo "Prochaines Étapes : Redémarrage système requis"
} | sudo tee -a "$SECURITY_REPORT"

echo "✅ Durcissement de sécurité terminé"
echo "📋 Rapport enregistré dans : $SECURITY_REPORT"
echo "🔄 Redémarrage système requis pour compléter le durcissement"

Notes Importantes

  • Redémarrage système requis - Les changements prennent effet seulement après redémarrage
  • Privilèges administrateur - Toutes les commandes nécessitent un accès sudo
  • Paramètres spécifiques aux applications - Ces scripts contrôlent seulement les paramètres à l'échelle du système
  • Compatibilité version macOS - Scripts testés sur macOS 10.14+
  • Conformité de confidentialité - Considérer les exigences légales dans votre juridiction
  • Notification utilisateur - Informer les utilisateurs des changements de politique de localisation

Dépannage

Problèmes Courants

Permission Refusée :

# Assurer le contexte approprié de l'utilisateur daemon
sudo -u "_locationd" defaults -currentHost read "/var/db/locationd/Library/Preferences/ByHost/com.apple.locationd"

Configuration Non Appliquée :

# Forcer le redémarrage du daemon de localisation
sudo launchctl unload /System/Library/LaunchDaemons/com.apple.locationd.plist
sudo launchctl load /System/Library/LaunchDaemons/com.apple.locationd.plist

Problèmes de Vérification :

# Vérifier l'intégrité du système
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate

N'oubliez pas de tester ces scripts sur des appareils individuels avant de les déployer dans votre environnement Roundfleet.