Guide

Nouvelles mises à jour et améliorations de Macfleet.

Gestion Entreprise de la Date et Heure sur macOS

Gérez les paramètres de date et heure dans votre MacFleet avec automation de niveau entreprise, contrôles de validation et capacités de surveillance complètes.

Comprendre la Gestion Entreprise de Date et Heure

La gestion de date et heure en entreprise nécessite plus qu'un simple réglage de date, exigeant :

  • Validation et formatage automatisés avec gestion d'erreurs de niveau entreprise
  • Opérations date/heure planifiées avec intégration de logique métier
  • Suivi de conformité pour exigences d'audit et standards réglementaires
  • Surveillance en temps réel des changements date/heure et intégrité système
  • Capacités d'intégration avec systèmes de planification et workflow d'entreprise
  • Contrôles de sécurité pour empêcher manipulation temporelle non autorisée

Processus de Base de Gestion Date et Heure

Commandes de Base

  1. Définir Date/Heure - date MMDDhhmm[[CC]YY][.ss]
  2. Définition Paramétrée - date $1 (avec passage d'argument)

Format Date de Base

Le format suit : MMDDhhmm[[CC]YY][.ss]

  • MM - Mois (01-12)
  • DD - Jour (01-31)
  • hh - Heure (00-23)
  • mm - Minutes (00-59)
  • CC - Siècle (optionnel)
  • YY - Année (optionnel)
  • ss - Secondes (optionnel)

Exemples de Configuration de Base

# Réglage de date de base
date 120614302023.00  # 6 décembre 2023 14h30

# Version paramétrée
date $1  # Passer la date comme argument

Système de Gestion Date et Heure Entreprise

#!/bin/bash

# Système de Gestion Date et Heure Entreprise MacFleet
# Gestion complète date/heure avec contrôles entreprise et surveillance

# Configuration
SCRIPT_NAME="Gestionnaire Date/Heure MacFleet"
VERSION="1.0.0"
LOG_FILE="/var/log/macfleet_datetime.log"
AUDIT_LOG="/var/log/macfleet_datetime_audit.log"
CONFIG_DIR="/etc/macfleet/datetime"
POLICIES_DIR="/etc/macfleet/datetime/policies"
BACKUP_DIR="/var/backups/datetime"
TEMP_DIR="/tmp/macfleet_datetime"
ORGANIZATION_NAME="MacFleet Entreprise"
DEPLOYMENT_MODE="enterprise"
ENABLE_VALIDATION=true
ENABLE_AUDIT_LOGGING=true
ENABLE_BACKUP_RESTORE=true
MAX_TIME_DRIFT_HOURS=24
BUSINESS_HOURS_START="08:00"
BUSINESS_HOURS_END="18:00"

# Modèles de Validation Date/Heure
declare -A DATE_FORMATS=(
    ["macfleet"]="MMDDhhmm[[CC]YY][.ss]"
    ["iso8601"]="YYYY-MM-DDTHH:MM:SS"
    ["unix"]="secondes_depuis_epoch"
    ["readable"]="Mois DD, YYYY HH:MM:SS"
)

# Politiques de Planification Entreprise
declare -A SCHEDULING_POLICIES=(
    ["immediate"]="executer_maintenant"
    ["business_hours"]="heures_ouverture_seulement"
    ["maintenance_window"]="maintenance_planifiee_seulement"
    ["emergency"]="outrepasser_toutes_restrictions"
)

# Standards de Conformité
declare -A COMPLIANCE_REQUIREMENTS=(
    ["SOX"]="piste_audit_financiere"
    ["HIPAA"]="integrite_temps_sante"
    ["PCI_DSS"]="precision_transaction_paiement"
    ["ISO27001"]="horodatage_securite_information"
)

# Créer les répertoires nécessaires
mkdir -p "$CONFIG_DIR"
mkdir -p "$POLICIES_DIR"
mkdir -p "$BACKUP_DIR"
mkdir -p "$TEMP_DIR"
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$AUDIT_LOG")"

# Définir les permissions sécurisées
chmod 755 "$CONFIG_DIR"
chmod 750 "$POLICIES_DIR"
chmod 750 "$BACKUP_DIR"
chmod 700 "$TEMP_DIR"

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

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

# Obtenir les informations actuelles de date et heure
get_current_datetime() {
    local format="${1:-all}"
    
    echo "=== Informations Date et Heure Actuelles ==="
    echo "Heure Locale : $(date '+%Y-%m-%d %H:%M:%S %Z')"
    echo "Heure UTC : $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
    echo "Timestamp Unix : $(date +%s)"
    echo "Uptime : $(uptime | awk -F'up ' '{print $2}' | awk -F',' '{print $1}')"
    
    case "$format" in
        "macfleet")
            echo "Format Macfleet : $(date '+%m%d%H%M%Y.%S')"
            ;;
        "iso8601")
            echo "Format ISO 8601 : $(date '+%Y-%m-%dT%H:%M:%S')"
            ;;
        "detailed")
            echo ""
            echo "Informations Détaillées :"
            echo "  Année : $(date '+%Y')"
            echo "  Mois : $(date '+%m') ($(date '+%B'))"
            echo "  Jour : $(date '+%d')"
            echo "  Heure : $(date '+%H')"
            echo "  Minute : $(date '+%M')"
            echo "  Seconde : $(date '+%S')"
            echo "  Jour de la Semaine : $(date '+%A')"
            echo "  Jour de l'Année : $(date '+%j')"
            echo "  Semaine de l'Année : $(date '+%U')"
            ;;
    esac
    echo ""
}

# Valider le format date/heure
validate_datetime_format() {
    local datetime_string="$1"
    local format_type="${2:-macfleet}"
    
    echo "=== Validation Format Date/Heure ==="
    echo "Entrée : $datetime_string"
    echo "Format Attendu : $format_type"
    echo ""
    
    case "$format_type" in
        "macfleet")
            # Valider format Macfleet : MMDDhhmm[[CC]YY][.ss]
            if [[ "$datetime_string" =~ ^[0-9]{8}([0-9]{4})?(\.[0-9]{2})?$ ]]; then
                local month="${datetime_string:0:2}"
                local day="${datetime_string:2:2}"
                local hour="${datetime_string:4:2}"
                local minute="${datetime_string:6:2}"
                
                # Valider les plages
                if [[ $month -ge 1 && $month -le 12 ]] && \
                   [[ $day -ge 1 && $day -le 31 ]] && \
                   [[ $hour -ge 0 && $hour -le 23 ]] && \
                   [[ $minute -ge 0 && $minute -le 59 ]]; then
                    echo "✅ Format Macfleet valide"
                    return 0
                else
                    echo "❌ Valeurs date/heure invalides dans format Macfleet"
                    return 1
                fi
            else
                echo "❌ Structure format Macfleet invalide"
                echo "Attendu : MMDDhhmm[[CC]YY][.ss]"
                return 1
            fi
            ;;
        "iso8601")
            # Valider format ISO 8601
            if date -j -f "%Y-%m-%dT%H:%M:%S" "$datetime_string" &>/dev/null; then
                echo "✅ Format ISO 8601 valide"
                return 0
            else
                echo "❌ Format ISO 8601 invalide"
                return 1
            fi
            ;;
        "unix")
            # Valider timestamp Unix
            if [[ "$datetime_string" =~ ^[0-9]+$ ]] && [[ $datetime_string -gt 0 ]]; then
                echo "✅ Timestamp Unix valide"
                return 0
            else
                echo "❌ Timestamp Unix invalide"
                return 1
            fi
            ;;
        *)
            echo "❌ Type de format inconnu : $format_type"
            return 1
            ;;
    esac
}

# Convertir entre formats de date
convert_datetime_format() {
    local input_datetime="$1"
    local from_format="$2"
    local to_format="$3"
    
    echo "=== Conversion Format Date/Heure ==="
    echo "Entrée : $input_datetime"
    echo "De : $from_format"
    echo "Vers : $to_format"
    echo ""
    
    local converted_datetime
    
    case "$from_format" in
        "macfleet")
            # Convertir depuis format Macfleet
            local month="${input_datetime:0:2}"
            local day="${input_datetime:2:2}"
            local hour="${input_datetime:4:2}"
            local minute="${input_datetime:6:2}"
            local year_part="${input_datetime:8:4}"
            local seconds_part="${input_datetime:13:2}"
            
            # Année par défaut si non fournie
            if [[ -z "$year_part" ]]; then
                year_part=$(date '+%Y')
            fi
            
            # Secondes par défaut si non fournies
            if [[ -z "$seconds_part" ]]; then
                seconds_part="00"
            fi
            
            case "$to_format" in
                "iso8601")
                    converted_datetime="${year_part}-${month}-${day}T${hour}:${minute}:${seconds_part}"
                    ;;
                "readable")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j "${month}${day}${hour}${minute}${year_part}.${seconds_part}" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "iso8601")
            # Convertir depuis format ISO 8601
            case "$to_format" in
                "macfleet")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
                "unix")
                    converted_datetime=$(date -j -f "%Y-%m-%dT%H:%M:%S" "$input_datetime" '+%s' 2>/dev/null)
                    ;;
            esac
            ;;
        "unix")
            # Convertir depuis timestamp Unix
            case "$to_format" in
                "macfleet")
                    converted_datetime=$(date -r "$input_datetime" '+%m%d%H%M%Y.%S' 2>/dev/null)
                    ;;
                "iso8601")
                    converted_datetime=$(date -r "$input_datetime" '+%Y-%m-%dT%H:%M:%S' 2>/dev/null)
                    ;;
                "readable")
                    converted_datetime=$(date -r "$input_datetime" '+%B %d, %Y %H:%M:%S' 2>/dev/null)
                    ;;
            esac
            ;;
    esac
    
    if [[ -n "$converted_datetime" ]]; then
        echo "✅ Conversion réussie"
        echo "Résultat : $converted_datetime"
        echo "$converted_datetime"
        return 0
    else
        echo "❌ Conversion échouée"
        return 1
    fi
}

# Définir date et heure avec validation entreprise
set_enterprise_datetime() {
    local datetime_input="$1"
    local format_type="${2:-macfleet}"
    local policy="${3:-business_hours}"
    local force="${4:-false}"
    local admin_user=$(whoami)
    
    log_security_event "DATETIME_CHANGE_ATTEMPT" "datetime=$datetime_input,format=$format_type,policy=$policy" "INFO"
    
    echo "=== Configuration Date/Heure Entreprise ==="
    echo "Entrée : $datetime_input"
    echo "Format : $format_type"
    echo "Politique : $policy"
    echo "Administrateur : $admin_user"
    echo "Mode Force : $force"
    echo ""
    
    # Valider le format d'entrée
    if ! validate_datetime_format "$datetime_input" "$format_type"; then
        log_operation "ERROR" "Format date/heure invalide : $datetime_input ($format_type)"
        return 1
    fi
    
    # Vérifier la politique de planification
    if [[ "$policy" == "business_hours" && "$force" != "true" ]]; then
        local current_hour=$(date '+%H')
        local business_start_hour="${BUSINESS_HOURS_START:0:2}"
        local business_end_hour="${BUSINESS_HOURS_END:0:2}"
        
        if [[ $current_hour -lt $business_start_hour || $current_hour -gt $business_end_hour ]]; then
            echo "⚠️  Opération demandée en dehors des heures d'ouverture ($BUSINESS_HOURS_START-$BUSINESS_HOURS_END)"
            echo "Utilisez force=true pour outrepasser ou attendez les heures d'ouverture"
            log_operation "WARNING" "Changement date/heure bloqué par politique heures d'ouverture"
            return 1
        fi
    fi
    
    # Sauvegarder date/heure actuelle
    local backup_file="$BACKUP_DIR/datetime_$(date +%Y%m%d_%H%M%S).backup"
    {
        echo "# Sauvegarde Date/Heure MacFleet"
        echo "PREVIOUS_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "PREVIOUS_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "PREVIOUS_UNIX=$(date +%s)"
        echo "BACKUP_TIMESTAMP=$(date)"
        echo "CHANGED_BY=$admin_user"
        echo "NEW_DATETIME=$datetime_input"
        echo "FORMAT_TYPE=$format_type"
        echo "POLICY=$policy"
    } > "$backup_file"
    
    log_operation "INFO" "Sauvegarde date/heure créée : $backup_file"
    
    # Convertir au format approprié si nécessaire
    local macfleet_format="$datetime_input"
    
    if [[ "$format_type" != "macfleet" ]]; then
        echo "Conversion $format_type vers format Macfleet..."
        macfleet_format=$(convert_datetime_format "$datetime_input" "$format_type" "macfleet")
        
        if [[ $? -ne 0 ]]; then
            log_operation "ERROR" "Échec conversion format date/heure"
            return 1
        fi
        
        echo "Format converti : $macfleet_format"
    fi
    
    # Valider la dérive temporelle
    local current_unix=$(date +%s)
    local target_unix=$(convert_datetime_format "$macfleet_format" "macfleet" "unix")
    local time_diff=$((target_unix - current_unix))
    local time_diff_hours=$((time_diff / 3600))
    local time_diff_abs=${time_diff_hours#-}
    
    if [[ $time_diff_abs -gt $MAX_TIME_DRIFT_HOURS && "$force" != "true" ]]; then
        echo "⚠️  Grand changement de temps détecté : ${time_diff_hours} heures"
        echo "Ceci dépasse le seuil de dérive maximum de $MAX_TIME_DRIFT_HOURS heures"
        echo "Utilisez force=true pour outrepasser cette vérification de sécurité"
        log_operation "WARNING" "Grande dérive temporelle bloquée : ${time_diff_hours} heures"
        return 1
    fi
    
    # Appliquer le changement date/heure
    echo "Définition date/heure sur : $macfleet_format"
    
    if sudo date "$macfleet_format" &>/dev/null; then
        echo "✅ Date/heure définie avec succès"
        log_operation "INFO" "Date/heure changée vers : $macfleet_format (format: $format_type)"
        log_security_event "DATETIME_CHANGED" "new_datetime=$macfleet_format,drift_hours=$time_diff_hours,policy=$policy" "INFO"
        
        # Vérifier le changement
        sleep 1
        echo ""
        echo "Vérification :"
        get_current_datetime
        
        return 0
    else
        echo "❌ Échec de définition date/heure"
        log_operation "ERROR" "Échec définition date/heure : $macfleet_format"
        log_security_event "DATETIME_CHANGE_FAILED" "datetime=$macfleet_format,error=date_command_failed" "ERROR"
        return 1
    fi
}

# Planifier les opérations date/heure
schedule_datetime_operation() {
    local operation="$1"
    local target_datetime="$2"
    local schedule_time="$3"
    local policy="${4:-business_hours}"
    
    echo "=== Opération Date/Heure Planifiée ==="
    echo "Opération : $operation"
    echo "Date/Heure Cible : $target_datetime"
    echo "Heure Planifiée : $schedule_time"
    echo "Politique : $policy"
    echo ""
    
    # Créer fichier d'opération planifiée
    local schedule_file="$POLICIES_DIR/scheduled_$(date +%Y%m%d_%H%M%S).sh"
    
    cat > "$schedule_file" << EOF
#!/bin/bash
# Opération Date/Heure Planifiée MacFleet
# Généré : $(date)
# Opération : $operation
# Cible : $target_datetime
# Politique : $policy

# Exécuter l'opération planifiée
case "$operation" in
    "set_datetime")
        $0 set "$target_datetime" macfleet "$policy" true
        ;;
    "sync_time")
        sudo systemsetup -setusingnetworktime on
        ;;
    "backup_datetime")
        $0 backup
        ;;
    *)
        echo "Opération inconnue : $operation"
        exit 1
        ;;
esac
EOF
    
    chmod +x "$schedule_file"
    
    # Planifier avec commande at (si disponible)
    if command -v at &>/dev/null; then
        echo "$schedule_file" | at "$schedule_time" 2>/dev/null
        
        if [[ $? -eq 0 ]]; then
            echo "✅ Opération planifiée avec succès pour $schedule_time"
            log_operation "INFO" "Opération planifiée : $operation à $schedule_time"
            return 0
        else
            echo "❌ Échec de planification de l'opération"
            log_operation "ERROR" "Échec planification opération : $operation"
            return 1
        fi
    else
        echo "⚠️  Commande 'at' non disponible pour planification"
        echo "Fichier de planification créé : $schedule_file"
        echo "Exécutez manuellement ou intégrez avec votre système de planification"
        return 1
    fi
}

# Surveiller l'intégrité date/heure
monitor_datetime_integrity() {
    local check_type="${1:-basic}"
    local admin_user=$(whoami)
    
    echo "=== Surveillance Intégrité Date/Heure ==="
    echo "Type de Vérification : $check_type"
    echo "Surveillant : $admin_user"
    echo ""
    
    local integrity_status="HEALTHY"
    local issues=()
    
    # Vérifier horloge système vs heure réseau
    if command -v ntpdate &>/dev/null; then
        echo "Vérification synchronisation horaire..."
        
        local ntp_time=$(ntpdate -q pool.ntp.org 2>/dev/null | tail -1 | grep -o "offset [+-][0-9.]*" | awk '{print $2}')
        
        if [[ -n "$ntp_time" ]]; then
            local offset_abs=${ntp_time#-}
            
            echo "Décalage NTP : ${ntp_time}s"
            
            if (( $(echo "$offset_abs > 30" | bc -l) )); then
                integrity_status="WARNING"
                issues+=("Grand décalage NTP : ${ntp_time}s")
            else
                echo "✅ Synchronisation horaire dans plage acceptable"
            fi
        else
            integrity_status="WARNING"
            issues+=("Impossible de vérifier synchronisation NTP")
        fi
    fi
    
    # Vérifier les changements de temps récents importants
    if [[ -f "$AUDIT_LOG" ]]; then
        echo ""
        echo "Vérification changements de temps récents..."
        
        local recent_changes=$(grep "DATETIME_CHANGED" "$AUDIT_LOG" | tail -5)
        
        if [[ -n "$recent_changes" ]]; then
            echo "Changements date/heure récents trouvés :"
            echo "$recent_changes" | while read -r line; do
                echo "  $(echo "$line" | cut -d'|' -f2,6)"
            done
        else
            echo "✅ Aucun changement date/heure récent détecté"
        fi
    fi
    
    # Vérifications avancées
    if [[ "$check_type" == "comprehensive" ]]; then
        echo ""
        echo "Exécution vérifications intégrité complètes..."
        
        # Vérifier logs système pour erreurs liées au temps
        local time_errors=$(log show --predicate 'subsystem == "com.apple.time"' --last 1h 2>/dev/null | grep -i error | wc -l)
        
        if [[ $time_errors -gt 0 ]]; then
            integrity_status="WARNING"
            issues+=("Erreurs temps système détectées : $time_errors")
        fi
        
        # Vérifier les incompatibilités de fuseau horaire
        local system_tz=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')
        local env_tz="$TZ"
        
        if [[ -n "$env_tz" && "$env_tz" != "$system_tz" ]]; then
            integrity_status="WARNING"
            issues+=("Incompatibilité fuseau horaire : système=$system_tz, env=$env_tz")
        fi
    fi
    
    # Générer rapport d'intégrité
    echo ""
    echo "=== Rapport Intégrité Date/Heure ==="
    echo "État Global : $integrity_status"
    echo "Horodatage : $(date)"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "Problèmes Trouvés :"
        printf '  - %s\n' "${issues[@]}"
    else
        echo "✅ Tous les systèmes date/heure fonctionnent normalement"
    fi
    
    # Enregistrer les résultats de surveillance
    log_operation "INFO" "Vérification intégrité date/heure terminée : $integrity_status (${#issues[@]} problèmes)"
    log_security_event "DATETIME_INTEGRITY_CHECK" "status=$integrity_status,issues=${#issues[@]}" "INFO"
    
    # Retourner le code de sortie approprié
    case "$integrity_status" in
        "HEALTHY") return 0 ;;
        "WARNING") return 1 ;;
        "CRITICAL") return 2 ;;
        *) return 3 ;;
    esac
}

# Générer rapport de gestion date/heure
generate_datetime_report() {
    local report_type="${1:-summary}"
    local admin_user=$(whoami)
    local report_file="/var/reports/datetime_report_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$report_file")"
    
    log_security_event "REPORT_GENERATION" "type=$report_type" "INFO"
    
    {
        echo "Rapport Gestion Date/Heure MacFleet"
        echo "=================================="
        echo "Type de Rapport : $report_type"
        echo "Généré : $(date)"
        echo "Généré Par : $admin_user"
        echo "Nom d'hôte : $(hostname)"
        echo ""
        
        case "$report_type" in
            "summary")
                echo "== Résumé Date/Heure =="
                get_current_datetime "detailed"
                
                echo "Formats Disponibles :"
                for format in "${!DATE_FORMATS[@]}"; do
                    echo "  $format: ${DATE_FORMATS[$format]}"
                done
                ;;
            "compliance")
                echo "== Évaluation Conformité =="
                
                echo "Standards de Conformité :"
                for standard in "${!COMPLIANCE_REQUIREMENTS[@]}"; do
                    echo "  $standard: ${COMPLIANCE_REQUIREMENTS[$standard]}"
                done
                
                echo ""
                echo "Événements d'Audit Récents :"
                if [[ -f "$AUDIT_LOG" ]]; then
                    tail -10 "$AUDIT_LOG"
                else
                    echo "Aucun log d'audit disponible"
                fi
                ;;
            "audit")
                echo "== Information d'Audit =="
                if [[ -f "$AUDIT_LOG" ]]; then
                    echo "Piste d'audit complète :"
                    cat "$AUDIT_LOG"
                else
                    echo "Aucun log d'audit disponible"
                fi
                ;;
        esac
        
        echo ""
        echo "== Informations Système =="
        echo "Uptime : $(uptime)"
        echo "Charge Moyenne : $(uptime | awk -F'load average:' '{print $2}')"
        
    } > "$report_file"
    
    echo "Rapport date/heure généré : $report_file"
    log_operation "INFO" "Rapport date/heure généré : $report_file"
}

# Sauvegarder et restaurer paramètres date/heure
backup_datetime_settings() {
    local backup_type="${1:-full}"
    
    echo "=== Sauvegarde Paramètres Date/Heure ==="
    echo "Type de Sauvegarde : $backup_type"
    echo ""
    
    local backup_file="$BACKUP_DIR/datetime_settings_$(date +%Y%m%d_%H%M%S).backup"
    
    {
        echo "# Sauvegarde Paramètres Date/Heure MacFleet"
        echo "BACKUP_DATE=$(date)"
        echo "BACKUP_TYPE=$backup_type"
        echo ""
        echo "# Paramètres Actuels"
        echo "CURRENT_DATETIME=$(date '+%Y-%m-%d %H:%M:%S %Z')"
        echo "CURRENT_UTC=$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
        echo "CURRENT_UNIX=$(date +%s)"
        echo "CURRENT_TIMEZONE=$(systemsetup -gettimezone 2>/dev/null | awk -F': ' '{print $2}')"
        echo "NETWORK_TIME=$(systemsetup -getusingnetworktime 2>/dev/null | awk -F': ' '{print $2}')"
        echo "TIME_SERVER=$(systemsetup -getnetworktimeserver 2>/dev/null | awk -F': ' '{print $2}')"
        echo ""
        echo "# Informations Système"
        echo "HOSTNAME=$(hostname)"
        echo "UPTIME=$(uptime)"
        echo "BACKUP_BY=$(whoami)"
    } > "$backup_file"
    
    echo "✅ Sauvegarde créée : $backup_file"
    log_operation "INFO" "Paramètres date/heure sauvegardés : $backup_file"
}

# Fonction principale de gestion date/heure
main() {
    local action="${1:-help}"
    
    case "$action" in
        "status"|"current")
            local format="${2:-all}"
            get_current_datetime "$format"
            ;;
        "set")
            local datetime_input="$2"
            local format_type="${3:-macfleet}"
            local policy="${4:-business_hours}"
            local force="$5"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage : $0 set <datetime> [format] [policy] [force]"
                echo "Exemple : $0 set 120614302023.00 macfleet business_hours"
                return 1
            fi
            
            set_enterprise_datetime "$datetime_input" "$format_type" "$policy" "$force"
            ;;
        "validate")
            local datetime_input="$2"
            local format_type="${3:-macfleet}"
            
            if [[ -z "$datetime_input" ]]; then
                echo "Usage : $0 validate <datetime> [format]"
                return 1
            fi
            
            validate_datetime_format "$datetime_input" "$format_type"
            ;;
        "convert")
            local datetime_input="$2"
            local from_format="$3"
            local to_format="$4"
            
            if [[ -z "$datetime_input" || -z "$from_format" || -z "$to_format" ]]; then
                echo "Usage : $0 convert <datetime> <from_format> <to_format>"
                echo "Formats disponibles : macfleet, iso8601, unix, readable"
                return 1
            fi
            
            convert_datetime_format "$datetime_input" "$from_format" "$to_format"
            ;;
        "schedule")
            local operation="$2"
            local target_datetime="$3"
            local schedule_time="$4"
            local policy="${5:-business_hours}"
            
            if [[ -z "$operation" || -z "$target_datetime" || -z "$schedule_time" ]]; then
                echo "Usage : $0 schedule <operation> <target_datetime> <schedule_time> [policy]"
                echo "Opérations : set_datetime, sync_time, backup_datetime"
                return 1
            fi
            
            schedule_datetime_operation "$operation" "$target_datetime" "$schedule_time" "$policy"
            ;;
        "monitor")
            local check_type="${2:-basic}"
            
            monitor_datetime_integrity "$check_type"
            ;;
        "backup")
            local backup_type="${2:-full}"
            
            backup_datetime_settings "$backup_type"
            ;;
        "report")
            local report_type="${2:-summary}"
            
            generate_datetime_report "$report_type"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Gestion Entreprise Date et Heure"
            echo ""
            echo "Usage : $0 <action> [options]"
            echo ""
            echo "Actions :"
            echo "  status [format]                         - Afficher informations date/heure actuelles"
            echo "  set <datetime> [format] [policy] [force] - Définir date/heure avec validation"
            echo "  validate <datetime> [format]            - Valider format date/heure"
            echo "  convert <datetime> <from> <to>          - Convertir entre formats"
            echo "  schedule <op> <datetime> <time> [policy] - Planifier opérations date/heure"
            echo "  monitor [type]                          - Surveiller intégrité date/heure"
            echo "  backup [type]                           - Sauvegarder paramètres date/heure"
            echo "  report [type]                           - Générer rapports date/heure"
            echo "  help                                    - Afficher ce message d'aide"
            echo ""
            echo "Formats Date/Heure :"
            for format in "${!DATE_FORMATS[@]}"; do
                echo "  $format: ${DATE_FORMATS[$format]}"
            done
            echo ""
            echo "Politiques de Planification :"
            for policy in "${!SCHEDULING_POLICIES[@]}"; do
                echo "  $policy: ${SCHEDULING_POLICIES[$policy]}"
            done
            echo ""
            echo "Types de Surveillance :"
            echo "  basic       - Vérifications intégrité de base"
            echo "  comprehensive - Surveillance étendue et validation"
            echo ""
            echo "Types de Rapport :"
            echo "  summary     - Aperçu date/heure (défaut)"
            echo "  compliance  - Évaluation conformité"
            echo "  audit       - Piste d'audit complète"
            echo ""
            echo "Exemples :"
            echo "  $0 set 120614302023.00                 - Définir date/heure en format Macfleet"
            echo "  $0 set '2023-12-06T14:30:00' iso8601   - Définir avec format ISO 8601"
            echo "  $0 convert 120614302023.00 macfleet iso8601 - Convertir formats"
            echo "  $0 schedule set_datetime 010108002024.00 '09:00 tomorrow' - Planifier opération"
            echo "  $0 monitor comprehensive               - Vérification intégrité complète"
            echo ""
            echo "Fonctionnalités :"
            echo "  • Gestion date/heure niveau entreprise"
            echo "  • Support et conversion formats multiples"
            echo "  • Application heures d'ouverture et politiques"
            echo "  • Validation complète et vérifications sécurité"
            echo "  • Journalisation audit et suivi conformité"
            echo "  • Opérations planifiées et automation"
            echo "  • Surveillance temps réel et vérifications intégrité"
            ;;
    esac
}

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

Commandes de Référence Rapide

Opérations Date/Heure de Base

# Vérifier statut date/heure actuel
./datetime_manager.sh status

# Définir date/heure avec format Macfleet (6 déc 2023 14h30)
./datetime_manager.sh set 120614302023.00

# Définir avec format ISO 8601
./datetime_manager.sh set "2023-12-06T14:30:00" iso8601

# Valider format date/heure avant définition
./datetime_manager.sh validate 120614302023.00 macfleet

Conversion de Format

# Convertir Macfleet vers ISO 8601
./datetime_manager.sh convert 120614302023.00 macfleet iso8601

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

# Convertir vers timestamp Unix
./datetime_manager.sh convert 120614302023.00 macfleet unix

Opérations Entreprise

# Définir avec application politique heures d'ouverture
./datetime_manager.sh set 120614302023.00 macfleet business_hours

# Forcer définition en dehors heures d'ouverture
./datetime_manager.sh set 120614302023.00 macfleet business_hours true

# Planifier opération date/heure future
./datetime_manager.sh schedule set_datetime 010108002024.00 "09:00 tomorrow"

Surveillance et Conformité

# Surveillance intégrité de base
./datetime_manager.sh monitor basic

# Surveillance complète
./datetime_manager.sh monitor comprehensive

# Générer rapport conformité
./datetime_manager.sh report compliance

# Sauvegarder paramètres actuels
./datetime_manager.sh backup full

Exemples d'Intégration

Intégration JAMF Pro

#!/bin/bash

# Script JAMF Pro pour gestion date/heure
# Paramètres : $4 = target_datetime, $5 = format, $6 = policy, $7 = force

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

# Télécharger gestionnaire datetime s'il n'est pas présent
if [[ ! -f "/usr/local/bin/macfleet_datetime_manager.sh" ]]; then
    curl -o "/usr/local/bin/macfleet_datetime_manager.sh" \
         "https://scripts.macfleet.com/datetime_manager.sh"
    chmod +x "/usr/local/bin/macfleet_datetime_manager.sh"
fi

# Définir date/heure avec contrôles entreprise
if [[ -n "$TARGET_DATETIME" ]]; then
    /usr/local/bin/macfleet_datetime_manager.sh set \
        "$TARGET_DATETIME" "$FORMAT" "$POLICY" "$FORCE"
    
    # Rapporter statut à JAMF
    if [[ $? -eq 0 ]]; then
        echo "Date/heure définie avec succès : $TARGET_DATETIME"
        exit 0
    else
        echo "Définition date/heure échouée : $TARGET_DATETIME"
        exit 1
    fi
else
    echo "Aucune date/heure cible fournie"
    exit 1
fi

Meilleures Pratiques

  1. Valider toutes entrées date/heure avant application des changements
  2. Utiliser politiques heures d'ouverture pour empêcher changements non autorisés
  3. Implémenter sauvegarde et restauration pour changements temps critiques
  4. Surveiller dérive temporelle en continu avec alertes automatisées
  5. Maintenir logs d'audit complets pour conformité
  6. Tester conversions formats avant déploiement production
  7. Coordonner avec équipes réseau pour synchronisation temporelle
  8. Documenter toutes opérations planifiées pour conscience opérationnelle

Ce système de gestion date et heure entreprise fournit un contrôle date/heure complet avec validation, planification, suivi de conformité et capacités d'automation de niveau entreprise pour une gestion temporelle MacFleet efficace.

Configurer les Paramètres de Trackpad sur macOS

Gérer les paramètres de trackpad dans votre MacFleet assure une expérience utilisateur cohérente et une productivité optimale. Ce tutoriel couvre les configurations de trackpad courantes avec des scripts shell pour le déploiement entreprise.

Comprendre les Paramètres de Trackpad

Les paramètres de trackpad sont stockés dans le domaine de préférences com.apple.AppleMultitouchTrackpad et nécessitent un contexte utilisateur pour une application correcte.

Fonction de Contexte Utilisateur de Base

Tous les scripts de trackpad nécessitent un contexte utilisateur approprié :

#!/bin/bash

# Obtenir l'utilisateur actuellement connecté
get_current_user() {
    /bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'
}

# Exécuter une commande dans le contexte utilisateur
execute_as_user() {
    local user="$1"
    local command="$2"
    su -l "$user" -c "$command"
}

Configuration de la Vitesse de Suivi

Définir la Vitesse de Suivi

#!/bin/bash

loggedInUser=$(get_current_user)

# Définir la vitesse de suivi (0.0 à 3.0)
# 0.0 = Lent, 1.5 = Moyen, 3.0 = Rapide
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad TrackingSpeed -float 1.5"

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

Configuration du Clic

Définir la Pression de Clic

#!/bin/bash

loggedInUser=$(get_current_user)

# Options de clic : 0 = Léger, 1 = Moyen, 2 = Ferme
execute_as_user "$loggedInUser" "defaults write com.apple.AppleMultitouchTrackpad FirstClickThreshold -int 1"

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

Activer le Clic Silencieux

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Paramètres Tap pour Cliquer

Activer Tap pour Cliquer

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Désactiver Tap pour Cliquer

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Clic Secondaire (Clic Droit)

Activer le Clic Secondaire à Deux Doigts

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Défilement Naturel

Activer le Défilement Naturel

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Désactiver le Défilement Naturel

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Fonction de Recherche

Désactiver la Recherche (Tap à Trois Doigts)

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Activer la Recherche

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Configuration du Verrouillage de Glissement

Activer le Verrouillage de Glissement

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Désactiver le Verrouillage de Glissement

#!/bin/bash

loggedInUser=$(get_current_user)

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

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

Script de Configuration Entreprise

Configuration complète du trackpad pour le déploiement entreprise :

#!/bin/bash

# Script de Configuration Trackpad pour MacFleet
# Compatible avec macOS 10.14+

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

# Obtenir l'utilisateur actuel
get_current_user() {
    /bin/ls -l /dev/console | /usr/bin/awk '{ print $3 }'
}

# Exécuter une commande dans le contexte utilisateur
execute_as_user() {
    local user="$1"
    local command="$2"
    su -l "$user" -c "$command"
}

# Fonction principale de configuration
configure_trackpad() {
    local current_user
    current_user=$(get_current_user)
    
    log_message "Début de la configuration du trackpad pour l'utilisateur : $current_user"
    
    # Définir la vitesse de suivi à moyen
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackingSpeed -float 1.5"; then
        log_message "✓ Vitesse de suivi définie à moyen"
    else
        log_message "✗ Échec de la définition de la vitesse de suivi"
    fi
    
    # Activer tap pour cliquer
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad Clicking -bool true"; then
        log_message "✓ Tap pour cliquer activé"
    else
        log_message "✗ Échec de l'activation du tap pour cliquer"
    fi
    
    # Activer le clic secondaire à deux doigts
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackpadRightClick -bool true"; then
        log_message "✓ Clic secondaire à deux doigts activé"
    else
        log_message "✗ Échec de l'activation du clic secondaire"
    fi
    
    # Activer le défilement naturel
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad TrackpadScroll -bool true"; then
        log_message "✓ Défilement naturel activé"
    else
        log_message "✗ Échec de l'activation du défilement naturel"
    fi
    
    # Définir la pression de clic à moyen
    if execute_as_user "$current_user" "defaults write com.apple.AppleMultitouchTrackpad FirstClickThreshold -int 1"; then
        log_message "✓ Pression de clic définie à moyen"
    else
        log_message "✗ Échec de la définition de la pression de clic"
    fi
    
    # Redémarrer la session utilisateur pour que les changements prennent effet
    if launchctl bootout user/$(id -u $current_user) 2>/dev/null; then
        log_message "✓ Session utilisateur redémarrée"
    else
        log_message "! Tentative de redémarrage de session utilisateur"
    fi
    
    log_message "Configuration du trackpad terminée"
    return 0
}

# Fonction de vérification
verify_configuration() {
    local current_user
    current_user=$(get_current_user)
    
    log_message "Vérification de la configuration du trackpad :"
    
    local tracking_speed
    tracking_speed=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad TrackingSpeed 2>/dev/null" || echo "non défini")
    log_message "  Vitesse de Suivi : $tracking_speed"
    
    local tap_click
    tap_click=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad Clicking 2>/dev/null" || echo "non défini")
    log_message "  Tap pour Cliquer : $tap_click"
    
    local right_click
    right_click=$(execute_as_user "$current_user" "defaults read com.apple.AppleMultitouchTrackpad TrackpadRightClick 2>/dev/null" || echo "non défini")
    log_message "  Clic Secondaire : $right_click"
}

# Exécuter la fonction principale
if configure_trackpad; then
    verify_configuration
    log_message "Script exécuté avec succès"
    exit 0
else
    log_message "Échec de l'exécution du script"
    exit 1
fi

Script de Vérification

Vérifier les paramètres actuels du trackpad :

#!/bin/bash

current_user=$(get_current_user)

echo "=== État des Paramètres de Trackpad ==="
echo "Vitesse de Suivi : $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackingSpeed 2>/dev/null" || echo 'Non configuré')"
echo "Tap pour Cliquer : $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad Clicking 2>/dev/null" || echo 'Non configuré')"
echo "Clic Secondaire : $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackpadRightClick 2>/dev/null" || echo 'Non configuré')"
echo "Défilement Naturel : $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad TrackpadScroll 2>/dev/null" || echo 'Non configuré')"
echo "Verrouillage de Glissement : $(su -l "$current_user" -c "defaults read com.apple.AppleMultitouchTrackpad DragLock 2>/dev/null" || echo 'Non configuré')"

Dépannage

ProblèmeSolution
Les paramètres ne s'appliquent pasS'assurer que le script s'exécute avec le contexte utilisateur approprié
Les changements reviennentUtiliser launchctl bootout pour redémarrer la session utilisateur
Permission refuséeExécuter le script avec des privilèges admin
Paramètres non visiblesRedémarrer l'app Préférences Système

Valeurs de Référence

Vitesse de Suivi

  • 0.0 - Lent
  • 1.5 - Moyen (recommandé)
  • 3.0 - Rapide

Pression de Clic

  • 0 - Clic léger
  • 1 - Clic moyen (recommandé)
  • 2 - Clic ferme

Notes Importantes

  • Tous les paramètres de trackpad nécessitent un redémarrage de session utilisateur pour prendre effet
  • Utiliser launchctl bootout user/$(id -u $user) pour redémarrer la session utilisateur
  • Tester les paramètres sur un petit groupe avant le déploiement à l'échelle de l'entreprise
  • Les utilisateurs peuvent manuellement remplacer ces paramètres dans Préférences Système

Analyse des Signatures de Code et Sécurité sur macOS

Analysez et gérez les signatures de code des applications sur vos appareils MacFleet pour améliorer la sécurité, vérifier l'authenticité des applications et implémenter les politiques de signature d'entreprise. Ce tutoriel couvre l'extraction des exigences de code, la vérification des signatures et l'analyse de sécurité complète.

Comprendre les Signatures de Code macOS

Les signatures de code sur macOS fournissent une vérification cryptographique que les applications n'ont pas été altérées et proviennent de sources fiables. Les composants clés incluent :

  • Exigences de Code - Contraintes que le code doit satisfaire pour être considéré comme valide
  • Identifiants de Bundle - Identifiants uniques pour les applications
  • Certificats de Développeur - Certificats numériques utilisés pour signer les applications
  • Droits - Permissions et capacités accordées aux applications

Importance de la Sécurité d'Entreprise

L'analyse des signatures de code est cruciale pour la sécurité d'entreprise :

  • Authenticité des Applications - Vérifier que les applications proviennent de développeurs de confiance
  • Détection d'Altération - Identifier les applications modifiées ou compromises
  • Application de Politique de Confidentialité - Contrôler l'accès aux données utilisateur protégées
  • Exigences de Conformité - Respecter les normes de sécurité pour les industries réglementées
  • Prévention des Malwares - Bloquer les applications non autorisées ou suspectes

Analyse de Base des Signatures de Code

Extraire les Exigences de Code

#!/bin/bash

# Extraction basique des exigences de code
APP_PATH="/System/Applications/Time Machine.app"

echo "Extraction des exigences de code pour : $APP_PATH"
codesign -dr - "$APP_PATH"

Extraction des Exigences de Code avec Gestion d'Erreurs

#!/bin/bash

# Extraction améliorée des exigences de code avec validation
extract_code_requirement() {
    local app_path="$1"
    
    # Valider l'entrée
    if [[ -z "$app_path" ]]; then
        echo "Erreur : Aucun chemin d'application fourni"
        echo "Usage : extract_code_requirement <chemin_app>"
        return 1
    fi
    
    # Vérifier si l'application existe
    if [[ ! -e "$app_path" ]]; then
        echo "Erreur : Application non trouvée au chemin : $app_path"
        return 1
    fi
    
    echo "=== Analyse des Exigences de Code ==="
    echo "Application : $app_path"
    echo ""
    
    # Extraire les exigences de code
    local code_req
    code_req=$(codesign -dr - "$app_path" 2>&1)
    
    if [[ $? -eq 0 ]]; then
        echo "Exigences de Code :"
        echo "$code_req"
        
        # Extraire seulement l'exigence désignée
        local designated_req
        designated_req=$(echo "$code_req" | grep "designated =>" | sed 's/designated => //')
        
        if [[ -n "$designated_req" ]]; then
            echo ""
            echo "Exigence Désignée :"
            echo "$designated_req"
        fi
    else
        echo "Erreur lors de l'extraction des exigences de code :"
        echo "$code_req"
        return 1
    fi
}

# Exemples d'utilisation
extract_code_requirement "/System/Applications/Safari.app"
extract_code_requirement "/Applications/Microsoft Word.app"

Analyse Complète de l'Application

#!/bin/bash

# Analyse complète de la signature d'application
analyze_application_signature() {
    local app_path="$1"
    local detailed="${2:-false}"
    
    if [[ ! -e "$app_path" ]]; then
        echo "Erreur : Application non trouvée : $app_path"
        return 1
    fi
    
    echo "=== Analyse Complète de la Signature d'Application ==="
    echo "Application : $app_path"
    echo "Date d'Analyse : $(date)"
    echo ""
    
    # Informations de base
    echo "--- Informations de Base ---"
    if [[ -d "$app_path" ]]; then
        local bundle_id
        bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Inconnu")
        echo "ID Bundle : $bundle_id"
        
        local app_version
        app_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Inconnue")
        echo "Version : $app_version"
    fi
    
    # Vérification de la signature de code
    echo ""
    echo "--- Vérification de la Signature de Code ---"
    if codesign -v "$app_path" 2>/dev/null; then
        echo "✓ La signature de code est valide"
    else
        echo "⚠️ La vérification de la signature de code a échoué"
    fi
    
    # Informations détaillées de signature
    echo ""
    echo "--- Détails de la Signature ---"
    codesign -dv "$app_path" 2>&1
    
    # Exigences de code
    echo ""
    echo "--- Exigences de Code ---"
    codesign -dr - "$app_path" 2>&1
    
    # Droits (si analyse détaillée demandée)
    if [[ "$detailed" == "true" ]]; then
        echo ""
        echo "--- Droits ---"
        codesign -d --entitlements - "$app_path" 2>/dev/null || echo "Aucun droit trouvé"
    fi
    
    echo ""
    echo "=== Analyse Terminée ==="
}

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

Gestion des Signatures de Code d'Entreprise

Analyse d'Applications par Lots

#!/bin/bash

# Analyser plusieurs applications pour la revue de sécurité d'entreprise
batch_analyze_applications() {
    local scan_path="${1:-/Applications}"
    local output_format="${2:-table}"
    local include_system="${3:-false}"
    
    echo "=== Analyse par Lots des Signatures d'Applications ==="
    echo "Chemin de Scan : $scan_path"
    echo "Inclure Apps Système : $include_system"
    echo "Format de Sortie : $output_format"
    echo ""
    
    local app_count=0
    local valid_count=0
    local invalid_count=0
    local results=()
    
    # Trouver toutes les applications
    local find_paths=("$scan_path")
    if [[ "$include_system" == "true" ]]; then
        find_paths+=("/System/Applications" "/System/Library/CoreServices")
    fi
    
    for search_path in "${find_paths[@]}"; do
        if [[ -d "$search_path" ]]; then
            while IFS= read -r -d '' app_path; do
                ((app_count++))
                
                local app_name=$(basename "$app_path" .app)
                local bundle_id="Inconnu"
                local signature_status="Invalide"
                local developer="Inconnu"
                local code_req="Inconnu"
                
                # Extraire l'ID bundle
                if [[ -f "$app_path/Contents/Info.plist" ]]; then
                    bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Inconnu")
                fi
                
                # Vérifier la validité de la signature
                if codesign -v "$app_path" 2>/dev/null; then
                    signature_status="Valide"
                    ((valid_count++))
                    
                    # Extraire les informations du développeur
                    local sig_info
                    sig_info=$(codesign -dv "$app_path" 2>&1)
                    developer=$(echo "$sig_info" | grep "Authority=" | head -1 | sed 's/Authority=//' | tr -d '\n')
                    
                    # Extraire l'exigence de code
                    code_req=$(codesign -dr - "$app_path" 2>/dev/null | grep "designated =>" | sed 's/designated => //')
                else
                    ((invalid_count++))
                fi
                
                # Stocker les résultats
                results+=("$app_name|$bundle_id|$signature_status|$developer|$code_req")
                
                # Indicateur de progression
                if (( app_count % 10 == 0 )); then
                    echo "Analysé $app_count applications..."
                fi
                
            done < <(find "$search_path" -name "*.app" -type d -print0 2>/dev/null)
        fi
    done
    
    echo ""
    echo "=== Résumé de l'Analyse ==="
    echo "Total des Applications : $app_count"
    echo "Signatures Valides : $valid_count"
    echo "Signatures Invalides : $invalid_count"
    echo ""
    
    # Sortir les résultats dans le format demandé
    case "$output_format" in
        "table")
            printf "%-30s %-40s %-10s %-50s\n" "Application" "ID Bundle" "Signature" "Développeur"
            printf "%-30s %-40s %-10s %-50s\n" "----------" "---------" "---------" "-----------"
            
            for result in "${results[@]}"; do
                IFS='|' read -r app_name bundle_id sig_status developer code_req <<< "$result"
                printf "%-30s %-40s %-10s %-50s\n" \
                    "${app_name:0:29}" \
                    "${bundle_id:0:39}" \
                    "$sig_status" \
                    "${developer:0:49}"
            done
            ;;
        "csv")
            echo "Application,ID Bundle,Statut Signature,Développeur,Exigence Code"
            for result in "${results[@]}"; do
                echo "$result" | tr '|' ','
            done
            ;;
        "json")
            echo "{"
            echo "  \"analysis_summary\": {"
            echo "    \"total_applications\": $app_count,"
            echo "    \"valid_signatures\": $valid_count,"
            echo "    \"invalid_signatures\": $invalid_count,"
            echo "    \"scan_date\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\""
            echo "  },"
            echo "  \"applications\": ["
            
            local first=true
            for result in "${results[@]}"; do
                IFS='|' read -r app_name bundle_id sig_status developer code_req <<< "$result"
                
                if [[ "$first" == "true" ]]; then
                    first=false
                else
                    echo ","
                fi
                
                echo -n "    {"
                echo -n "\"name\": \"$app_name\", "
                echo -n "\"bundle_id\": \"$bundle_id\", "
                echo -n "\"signature_valid\": $([ "$sig_status" == "Valide" ] && echo "true" || echo "false"), "
                echo -n "\"developer\": \"$developer\", "
                echo -n "\"code_requirement\": \"$code_req\""
                echo -n "}"
            done
            
            echo ""
            echo "  ]"
            echo "}"
            ;;
    esac
}

# Exemples d'utilisation
batch_analyze_applications "/Applications" "table" "false"
batch_analyze_applications "/Applications" "json" "true" > /tmp/app_analysis.json

Système de Gestion des Signatures de Code d'Entreprise

#!/bin/bash

# Outil de Gestion des Signatures de Code MacFleet
# Analyse complète des signatures de code et application des politiques de sécurité

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

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

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

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

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

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

# Analyse avancée des signatures de code
analyze_code_signature() {
    local app_path="$1"
    local output_format="${2:-detailed}"
    local security_check="${3:-true}"
    
    log_action "Analyse de la signature de code pour : $app_path"
    
    if [[ ! -e "$app_path" ]]; then
        log_action "ERREUR : Application non trouvée : $app_path"
        return 1
    fi
    
    local analysis_data=()
    local app_name=$(basename "$app_path" .app)
    
    echo "=== Analyse Avancée des Signatures de Code ==="
    echo "Application : $app_name"
    echo "Chemin : $app_path"
    echo "Date d'Analyse : $(date)"
    echo ""
    
    # Informations de base de l'application
    extract_app_metadata "$app_path" analysis_data
    
    # Vérification de la signature de code
    verify_code_signature "$app_path" analysis_data
    
    # Extraire les exigences de code
    extract_code_requirements "$app_path" analysis_data
    
    # Analyse de sécurité
    if [[ "$security_check" == "true" ]]; then
        perform_security_analysis "$app_path" analysis_data
    fi
    
    # Générer la sortie dans le format demandé
    case "$output_format" in
        "detailed")
            display_detailed_analysis analysis_data
            ;;
        "summary")
            display_summary_analysis analysis_data
            ;;
        "json")
            generate_json_analysis "$app_path" analysis_data
            ;;
        "csv")
            generate_csv_analysis "$app_path" analysis_data
            ;;
    esac
    
    log_action "Analyse de signature de code terminée pour : $app_path"
}

# Extraire les métadonnées de l'application
extract_app_metadata() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo "--- Métadonnées de l'Application ---"
    
    if [[ -f "$app_path/Contents/Info.plist" ]]; then
        local bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Inconnu")
        local version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null || echo "Inconnue")
        local build=$(defaults read "$app_path/Contents/Info.plist" CFBundleVersion 2>/dev/null || echo "Inconnue")
        local min_os=$(defaults read "$app_path/Contents/Info.plist" LSMinimumSystemVersion 2>/dev/null || echo "Inconnu")
        
        echo "ID Bundle : $bundle_id"
        echo "Version : $version"
        echo "Build : $build"
        echo "OS Minimum : $min_os"
        
        data_ref+=("bundle_id:$bundle_id")
        data_ref+=("version:$version")
        data_ref+=("build:$build")
        data_ref+=("min_os:$min_os")
    else
        echo "Aucun Info.plist trouvé"
        data_ref+=("bundle_id:Inconnu")
    fi
    
    # Taille du fichier et date de modification
    local file_size=$(du -sh "$app_path" | cut -f1)
    local mod_date=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path")
    
    echo "Taille de l'Application : $file_size"
    echo "Dernière Modification : $mod_date"
    
    data_ref+=("size:$file_size")
    data_ref+=("modified:$mod_date")
}

# Vérifier la signature de code
verify_code_signature() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Vérification de la Signature de Code ---"
    
    # Vérification de base
    if codesign -v "$app_path" 2>/dev/null; then
        echo "✓ La signature de code est valide"
        data_ref+=("signature_valid:true")
        
        # Informations détaillées de signature
        local sig_info=$(codesign -dv "$app_path" 2>&1)
        
        # Extraire les informations clés
        local identifier=$(echo "$sig_info" | grep "Identifier=" | sed 's/Identifier=//')
        local format=$(echo "$sig_info" | grep "Format=" | sed 's/Format=//')
        local cdhash=$(echo "$sig_info" | grep "CDHash=" | sed 's/CDHash=//')
        local team_id=$(echo "$sig_info" | grep "TeamIdentifier=" | sed 's/TeamIdentifier=//')
        
        echo "Identifiant : $identifier"
        echo "Format : $format"
        echo "CDHash : $cdhash"
        echo "ID Équipe : $team_id"
        
        data_ref+=("identifier:$identifier")
        data_ref+=("format:$format")
        data_ref+=("cdhash:$cdhash")
        data_ref+=("team_id:$team_id")
        
        # Extraire la chaîne de certificats
        local authorities=$(echo "$sig_info" | grep "Authority=" | sed 's/Authority=//')
        echo "Chaîne de Certificats :"
        while IFS= read -r authority; do
            echo "  - $authority"
        done <<< "$authorities"
        
        data_ref+=("authorities:$authorities")
        
    else
        echo "⚠️ La vérification de la signature de code a ÉCHOUÉ"
        data_ref+=("signature_valid:false")
        
        local error=$(codesign -v "$app_path" 2>&1)
        echo "Erreur : $error"
        data_ref+=("signature_error:$error")
    fi
}

# Extraire les exigences de code
extract_code_requirements() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Exigences de Code ---"
    
    local req_output=$(codesign -dr - "$app_path" 2>&1)
    
    if [[ $? -eq 0 ]]; then
        echo "$req_output"
        
        # Extraire l'exigence désignée
        local designated_req=$(echo "$req_output" | grep "designated =>" | sed 's/designated => //')
        if [[ -n "$designated_req" ]]; then
            echo ""
            echo "Exigence Désignée :"
            echo "$designated_req"
            data_ref+=("designated_requirement:$designated_req")
        fi
        
        data_ref+=("requirements_extracted:true")
    else
        echo "Échec de l'extraction des exigences de code"
        echo "$req_output"
        data_ref+=("requirements_extracted:false")
    fi
}

# Effectuer une analyse de sécurité
perform_security_analysis() {
    local app_path="$1"
    local -n data_ref=$2
    
    echo ""
    echo "--- Analyse de Sécurité ---"
    
    local security_score=100
    local security_issues=()
    
    # Vérifier si l'application est signée
    if ! codesign -v "$app_path" 2>/dev/null; then
        security_score=$((security_score - 50))
        security_issues+=("L'application n'est pas signée")
    fi
    
    # Vérifier le runtime durci
    local flags=$(codesign -dv "$app_path" 2>&1 | grep "CodeDirectory" | grep "runtime")
    if [[ -n "$flags" ]]; then
        echo "✓ Runtime durci activé"
        data_ref+=("hardened_runtime:true")
    else
        echo "⚠️ Runtime durci non activé"
        security_score=$((security_score - 20))
        security_issues+=("Runtime durci non activé")
        data_ref+=("hardened_runtime:false")
    fi
    
    # Vérifier la notarisation
    if spctl -a -v "$app_path" 2>&1 | grep -q "notarized"; then
        echo "✓ L'application est notarisée"
        data_ref+=("notarized:true")
    else
        echo "⚠️ L'application n'est pas notarisée"
        security_score=$((security_score - 15))
        security_issues+=("Application non notarisée")
        data_ref+=("notarized:false")
    fi
    
    # Vérifier les vulnérabilités connues (vérification de base)
    check_known_vulnerabilities "$app_path" security_score security_issues
    
    echo ""
    echo "Score de Sécurité : $security_score/100"
    data_ref+=("security_score:$security_score")
    
    if [[ ${#security_issues[@]} -gt 0 ]]; then
        echo "Problèmes de Sécurité Trouvés :"
        for issue in "${security_issues[@]}"; do
            echo "  ⚠️ $issue"
        done
        data_ref+=("security_issues:${security_issues[*]}")
    else
        echo "✓ Aucun problème de sécurité trouvé"
        data_ref+=("security_issues:none")
    fi
}

# Vérifier les vulnérabilités connues
check_known_vulnerabilities() {
    local app_path="$1"
    local -n score_ref=$2
    local -n issues_ref=$3
    
    local bundle_id
    bundle_id=$(defaults read "$app_path/Contents/Info.plist" CFBundleIdentifier 2>/dev/null || echo "Inconnu")
    
    # Vérifier contre les applications vulnérables connues (exemple simplifié)
    case "$bundle_id" in
        "com.adobe.flashplayer"*)
            score_ref=$((score_ref - 30))
            issues_ref+=("Flash Player a des vulnérabilités de sécurité connues")
            ;;
        "com.java."*)
            # Vérifier la version Java pour les vulnérabilités connues
            local java_version
            java_version=$(defaults read "$app_path/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
            if [[ -n "$java_version" ]]; then
                echo "Version Java détectée : $java_version"
                # Ajouter des vérifications de version spécifiques ici
            fi
            ;;
    esac
    
    # Vérifier les applications avec des certificats expirés
    local cert_info=$(codesign -dv "$app_path" 2>&1 | grep "Timestamp=")
    if [[ -n "$cert_info" ]]; then
        # Extraire l'horodatage et vérifier si le certificat est ancien
        local timestamp=$(echo "$cert_info" | sed 's/Timestamp=//')
        echo "Horodatage du certificat : $timestamp"
    fi
}

# Générer une analyse complète de la flotte
analyze_fleet_applications() {
    local scan_paths=("$@")
    local report_file="$REPORT_DIR/fleet_analysis_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Analyse des Applications à l'Échelle de la Flotte ==="
    echo "Chemins de scan : ${scan_paths[*]}"
    echo ""
    
    local total_apps=0
    local signed_apps=0
    local unsigned_apps=0
    local notarized_apps=0
    local security_issues=0
    local applications=()
    
    for scan_path in "${scan_paths[@]}"; do
        if [[ -d "$scan_path" ]]; then
            echo "Scan : $scan_path"
            
            while IFS= read -r -d '' app_path; do
                ((total_apps++))
                
                local app_name=$(basename "$app_path" .app)
                local analysis_data=()
                
                # Analyse rapide pour aperçu de la flotte
                analyze_code_signature "$app_path" "summary" "true" > /dev/null
                
                # Extraire les métriques clés
                if codesign -v "$app_path" 2>/dev/null; then
                    ((signed_apps++))
                else
                    ((unsigned_apps++))
                fi
                
                if spctl -a -v "$app_path" 2>&1 | grep -q "notarized"; then
                    ((notarized_apps++))
                fi
                
                # Ajouter au tableau des applications
                applications+=("$app_path")
                
                # Indicateur de progression
                if (( total_apps % 25 == 0 )); then
                    echo "Analysé $total_apps applications..."
                fi
                
            done < <(find "$scan_path" -name "*.app" -type d -maxdepth 2 -print0 2>/dev/null)
        fi
    done
    
    # Générer le rapport d'analyse de flotte
    cat > "$report_file" << EOF
{
    "fleet_analysis": {
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "scan_paths": [$(printf '"%s",' "${scan_paths[@]}" | sed 's/,$//')],
        "summary": {
            "total_applications": $total_apps,
            "signed_applications": $signed_apps,
            "unsigned_applications": $unsigned_apps,
            "notarized_applications": $notarized_apps,
            "signing_compliance": $(( signed_apps * 100 / total_apps )),
            "notarization_compliance": $(( notarized_apps * 100 / total_apps ))
        },
        "analysis_date": "$(date)",
        "script_version": "$SCRIPT_VERSION"
    }
}
EOF
    
    echo ""
    echo "=== Résumé de l'Analyse de Flotte ==="
    echo "Total des Applications : $total_apps"
    echo "Applications Signées : $signed_apps ($(( signed_apps * 100 / total_apps ))%)"
    echo "Applications Non Signées : $unsigned_apps ($(( unsigned_apps * 100 / total_apps ))%)"
    echo "Applications Notarisées : $notarized_apps ($(( notarized_apps * 100 / total_apps ))%)"
    echo ""
    echo "Rapport d'analyse de flotte : $report_file"
    
    log_action "Analyse de flotte terminée : $total_apps applications analysées"
}

# Fonction d'exécution principale
main() {
    local action="${1:-help}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Gestion des Signatures de Code MacFleet Démarrée ==="
    log_action "Action : $action"
    
    case "$action" in
        "analyze")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 analyze <chemin_app> [format_sortie] [vérification_sécurité]"
                echo "Formats de sortie : detailed, summary, json, csv"
                exit 1
            fi
            analyze_code_signature "$param1" "${param2:-detailed}" "${param3:-true}"
            ;;
        "extract")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 extract <chemin_app>"
                exit 1
            fi
            extract_code_requirement "$param1"
            ;;
        "batch")
            if [[ -z "$param1" ]]; then
                param1="/Applications"
            fi
            batch_analyze_applications "$param1" "${param2:-table}" "${param3:-false}"
            ;;
        "fleet")
            local paths=("${@:2}")
            if [[ ${#paths[@]} -eq 0 ]]; then
                paths=("/Applications" "/System/Applications")
            fi
            analyze_fleet_applications "${paths[@]}"
            ;;
        "verify")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 verify <chemin_app>"
                exit 1
            fi
            if codesign -v "$param1" 2>/dev/null; then
                echo "✓ La signature de code est valide pour : $param1"
            else
                echo "⚠️ La vérification de la signature de code a échoué pour : $param1"
                codesign -v "$param1"
            fi
            ;;
        "help")
            echo "Usage : $0 [action] [options...]"
            echo "Actions :"
            echo "  analyze <chemin_app> [format] [sécurité] - Analyser la signature de l'application"
            echo "  extract <chemin_app> - Extraire seulement l'exigence de code"
            echo "  batch <chemin_scan> [format] [inclure_système] - Analyser les applications par lots"
            echo "  fleet [chemins...] - Analyser les applications à l'échelle de la flotte"
            echo "  verify <chemin_app> - Vérification rapide de signature"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Formats de Sortie : detailed, summary, json, csv, table"
            echo "Politiques : ${!SIGNING_POLICIES[*]}"
            echo "Niveaux de Sécurité : ${!SECURITY_LEVELS[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion des signatures de code terminée ==="
}

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

Meilleures Pratiques de Sécurité

Gestion des Certificats d'Entreprise

#!/bin/bash

# Validation des certificats d'entreprise
validate_enterprise_certificates() {
    local cert_policy="${1:-strict}"
    
    echo "=== Validation des Certificats d'Entreprise ==="
    echo "Politique : $cert_policy"
    echo ""
    
    local expired_certs=()
    local revoked_certs=()
    local untrusted_certs=()
    
    # Vérifier le trousseau système pour les certificats d'entreprise
    security find-certificate -a -p /Library/Keychains/System.keychain | \
    while IFS= read -r cert_line; do
        if [[ "$cert_line" == "-----BEGIN CERTIFICATE-----" ]]; then
            # Traiter le certificat
            echo "Vérification du certificat d'entreprise..."
        fi
    done
    
    echo "✓ Validation des certificats d'entreprise terminée"
}

validate_enterprise_certificates "strict"

Rapport de Conformité

#!/bin/bash

# Générer un rapport de conformité pour les exigences réglementaires
generate_compliance_report() {
    local compliance_type="${1:-general}"
    local output_file="$REPORT_DIR/compliance_${compliance_type}_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Génération du Rapport de Conformité : $compliance_type ==="
    
    local total_apps=0
    local compliant_apps=0
    local non_compliant_apps=0
    
    # Scanner les applications pour la conformité
    while IFS= read -r -d '' app_path; do
        ((total_apps++))
        
        case "$compliance_type" in
            "hipaa")
                check_hipaa_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            "sox")
                check_sox_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            "pci_dss")
                check_pci_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
            *)
                check_general_compliance "$app_path" compliant_apps non_compliant_apps
                ;;
        esac
    done < <(find /Applications -name "*.app" -type d -print0 2>/dev/null)
    
    # Générer le rapport
    local compliance_percentage=$(( compliant_apps * 100 / total_apps ))
    
    cat > "$output_file" << EOF
{
    "compliance_report": {
        "type": "$compliance_type",
        "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
        "hostname": "$(hostname)",
        "summary": {
            "total_applications": $total_apps,
            "compliant_applications": $compliant_apps,
            "non_compliant_applications": $non_compliant_apps,
            "compliance_percentage": $compliance_percentage
        }
    }
}
EOF
    
    echo "Rapport de conformité généré : $output_file"
    echo "Taux de conformité : $compliance_percentage%"
}

generate_compliance_report "general"

Notes Importantes

  • Les signatures de code vérifient l'authenticité et l'intégrité des applications
  • Les exigences de code spécifient les contraintes pour la validation des applications
  • Les politiques d'entreprise doivent équilibrer sécurité et besoins opérationnels
  • La surveillance régulière aide à détecter les applications non autorisées
  • Les exigences de conformité varient selon l'industrie et le cadre réglementaire
  • La notarisation fournit une validation de sécurité supplémentaire d'Apple
  • La gestion des certificats est cruciale pour la sécurité d'entreprise
  • L'analyse à l'échelle de la flotte permet une gestion proactive de la sécurité

Gestion Entreprise du Client Itinérant Cisco Umbrella sur macOS

Déployez et gérez les clients itinérants Cisco Umbrella dans votre MacFleet avec une protection DNS de sécurité de niveau entreprise, des workflows de déploiement automatisés et des capacités de surveillance complètes. Ce tutoriel transforme le processus de déploiement de base en une solution de sécurité d'entreprise robuste.

Comprendre la Gestion Cisco Umbrella Entreprise

Le déploiement Cisco Umbrella en entreprise nécessite plus qu'une simple installation de client, exigeant :

  • Workflows de déploiement automatisés avec configurations spécifiques à l'organisation
  • Gestion centralisée des politiques de sécurité avec contrôles de filtrage DNS
  • Surveillance et rapports en temps réel des menaces et activités de sécurité
  • Gestion des certificats pour les fonctionnalités de sécurité avancées
  • Suivi de conformité pour la gestion de la posture de sécurité
  • Capacités d'intégration avec l'infrastructure de sécurité existante

Processus de Déploiement Cisco Umbrella de Base

Composants de Déploiement Basiques

  1. Push de Configuration - Déployer OrgInfo.plist avec paramètres d'organisation
  2. Installation PKG - Installer l'application client itinérant Umbrella
  3. Distribution de Certificats - Déployer les certificats racine pour les fonctionnalités avancées
  4. Application de Politiques - Configurer les politiques de sécurité et surveillance

Script de Configuration de Base

# Script de configuration de base
mkdir "/Library/Application Support/OpenDNS Roaming Client/"
cat <<EOF > "/Library/Application Support/OpenDNS Roaming Client/OrgInfo.plist"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>APIFingerprint</key>
    <string>xxxxxxxxxxx</string>
    <key>APIOrganizationID</key>
    <string>xxxxxx</string>
    <key>APIUserID</key>
    <string>xxxxx</string>
    <key>InstallMenubar</key>
    <false/>
</dict>
</plist>
EOF

Système de Gestion Cisco Umbrella Entreprise

#!/bin/bash

# Système de Gestion Cisco Umbrella Entreprise MacFleet
# Déploiement DNS de sécurité complet avec contrôles entreprise et surveillance

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

# Paramètres de Configuration Umbrella (à personnaliser par organisation)
declare -A UMBRELLA_CONFIG_PARAMS=(
    ["APIFingerprint"]=""           # À remplir depuis le tableau de bord Cisco
    ["APIOrganizationID"]=""        # À remplir depuis le tableau de bord Cisco
    ["APIUserID"]=""                # À remplir depuis le tableau de bord Cisco
    ["InstallMenubar"]="false"
    ["EnableLogging"]="true"
    ["LogLevel"]="INFO"
    ["UpdateInterval"]="3600"
    ["BackupDNS"]="8.8.8.8,1.1.1.1"
    ["EnforceSecureDNS"]="true"
    ["BlockMalware"]="true"
    ["BlockPhishing"]="true"
    ["BlockAdware"]="true"
    ["ContentFiltering"]="true"
    ["SafeSearch"]="true"
    ["YouTubeFiltering"]="strict"
)

# Modèles de Politiques de Sécurité
declare -A SECURITY_POLICIES=(
    ["executive"]="securite_elevee_blocage_minimal"
    ["standard"]="securite_equilibree_blocage_modere"
    ["guest"]="securite_basique_blocage_etendu"
    ["developer"]="securite_moyenne_blocage_minimal"
    ["kiosk"]="securite_maximale_blocage_etendu"
)

# Créer les répertoires nécessaires
mkdir -p "$CONFIG_DIR"
mkdir -p "$CERTS_DIR"
mkdir -p "$POLICIES_DIR"
mkdir -p "$TEMP_DIR"
mkdir -p "$BACKUP_DIR"
mkdir -p "$(dirname "$LOG_FILE")"
mkdir -p "$(dirname "$AUDIT_LOG")"

# Définir les permissions sécurisées
chmod 755 "$CONFIG_DIR"
chmod 700 "$CERTS_DIR"
chmod 750 "$POLICIES_DIR"
chmod 700 "$TEMP_DIR"
chmod 750 "$BACKUP_DIR"

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

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

# Valider les paramètres de configuration Cisco Umbrella
validate_umbrella_config() {
    local errors=()
    
    # Vérifier les paramètres API requis
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" ]]; then
        errors+=("APIFingerprint est requis")
    fi
    
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIOrganizationID]}" ]]; then
        errors+=("APIOrganizationID est requis")
    fi
    
    if [[ -z "${UMBRELLA_CONFIG_PARAMS[APIUserID]}" ]]; then
        errors+=("APIUserID est requis")
    fi
    
    # Valider le format de l'empreinte (vérification basique)
    if [[ -n "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" ]] && [[ ! "${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}" =~ ^[A-Fa-f0-9]{40,}$ ]]; then
        errors+=("Le format de l'APIFingerprint semble invalide")
    fi
    
    if [[ ${#errors[@]} -gt 0 ]]; then
        echo "Validation de la configuration Umbrella échouée :"
        printf '  - %s\n' "${errors[@]}"
        return 1
    fi
    
    return 0
}

# Générer la configuration Umbrella entreprise
generate_umbrella_config() {
    local user_profile="${1:-standard}"
    local custom_settings="${2:-}"
    local admin_user=$(whoami)
    
    log_security_event "CONFIG_GENERATION" "profile=$user_profile" "INFO"
    
    echo "=== Génération Configuration Cisco Umbrella ==="
    echo "Profil Utilisateur : $user_profile"
    echo "Mode de Déploiement : $DEPLOYMENT_MODE"
    echo "Administrateur : $admin_user"
    echo ""
    
    # Valider la configuration avant génération
    if ! validate_umbrella_config; then
        log_operation "ERROR" "Validation de configuration échouée"
        return 1
    fi
    
    # Sauvegarder la configuration existante
    if [[ -f "$UMBRELLA_CONFIG" ]]; then
        local backup_file="$BACKUP_DIR/OrgInfo_$(date +%Y%m%d_%H%M%S).plist"
        cp "$UMBRELLA_CONFIG" "$backup_file"
        log_operation "INFO" "Configuration existante sauvegardée dans : $backup_file"
    fi
    
    # Appliquer les paramètres de sécurité spécifiques au profil
    case "$user_profile" in
        "executive")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="WARN"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="false"
            ;;
        "standard")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="INFO"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            ;;
        "guest")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="WARN"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            UMBRELLA_CONFIG_PARAMS["SafeSearch"]="true"
            ;;
        "developer")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="DEBUG"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="true"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="false"
            ;;
        "kiosk")
            UMBRELLA_CONFIG_PARAMS["LogLevel"]="ERROR"
            UMBRELLA_CONFIG_PARAMS["InstallMenubar"]="false"
            UMBRELLA_CONFIG_PARAMS["ContentFiltering"]="true"
            UMBRELLA_CONFIG_PARAMS["EnforceSecureDNS"]="true"
            ;;
    esac
    
    # Générer le fichier de configuration
    cat > "$UMBRELLA_CONFIG" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <!-- Configuration API Cisco Umbrella de Base -->
    <key>APIFingerprint</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIFingerprint]}</string>
    <key>APIOrganizationID</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIOrganizationID]}</string>
    <key>APIUserID</key>
    <string>${UMBRELLA_CONFIG_PARAMS[APIUserID]}</string>
    
    <!-- Configuration Interface Utilisateur Entreprise -->
    <key>InstallMenubar</key>
    <${UMBRELLA_CONFIG_PARAMS[InstallMenubar]}/>
    <key>ShowNotifications</key>
    <true/>
    <key>AutoStart</key>
    <true/>
    
    <!-- Journalisation et Surveillance -->
    <key>EnableLogging</key>
    <${UMBRELLA_CONFIG_PARAMS[EnableLogging]}/>
    <key>LogLevel</key>
    <string>${UMBRELLA_CONFIG_PARAMS[LogLevel]}</string>
    <key>LogRotationDays</key>
    <integer>30</integer>
    
    <!-- Configuration Réseau -->
    <key>UpdateInterval</key>
    <integer>${UMBRELLA_CONFIG_PARAMS[UpdateInterval]}</integer>
    <key>BackupDNS</key>
    <string>${UMBRELLA_CONFIG_PARAMS[BackupDNS]}</string>
    <key>EnforceSecureDNS</key>
    <${UMBRELLA_CONFIG_PARAMS[EnforceSecureDNS]}/>
    
    <!-- Politiques de Sécurité -->
    <key>BlockMalware</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockMalware]}/>
    <key>BlockPhishing</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockPhishing]}/>
    <key>BlockAdware</key>
    <${UMBRELLA_CONFIG_PARAMS[BlockAdware]}/>
    
    <!-- Filtrage de Contenu -->
    <key>ContentFiltering</key>
    <${UMBRELLA_CONFIG_PARAMS[ContentFiltering]}/>
    <key>SafeSearch</key>
    <${UMBRELLA_CONFIG_PARAMS[SafeSearch]}/>
    <key>YouTubeFiltering</key>
    <string>${UMBRELLA_CONFIG_PARAMS[YouTubeFiltering]}</string>
    
    <!-- Métadonnées Entreprise -->
    <key>OrganizationName</key>
    <string>$ORGANIZATION_NAME</string>
    <key>DeploymentMode</key>
    <string>$DEPLOYMENT_MODE</string>
    <key>ConfigurationVersion</key>
    <string>$(date +%Y%m%d%H%M%S)</string>
    <key>DeployedBy</key>
    <string>$admin_user</string>
    <key>DeploymentDate</key>
    <string>$(date)</string>
    <key>UserProfile</key>
    <string>$user_profile</string>
</dict>
</plist>
EOF
    
    # Définir les permissions sécurisées
    chmod 644 "$UMBRELLA_CONFIG"
    chown root:wheel "$UMBRELLA_CONFIG"
    
    # Valider la configuration générée
    if plutil -lint "$UMBRELLA_CONFIG" &>/dev/null; then
        echo "✅ Configuration générée avec succès"
        log_operation "INFO" "Configuration Umbrella générée pour le profil : $user_profile"
        log_security_event "CONFIG_DEPLOYED" "profile=$user_profile,file=$UMBRELLA_CONFIG" "INFO"
        return 0
    else
        echo "❌ Validation de configuration échouée"
        log_operation "ERROR" "Le fichier de configuration généré est invalide"
        return 1
    fi
}

# Installer les certificats Cisco Umbrella
install_umbrella_certificates() {
    local cert_source="${1:-auto}"
    local admin_user=$(whoami)
    
    log_security_event "CERT_INSTALLATION" "source=$cert_source" "INFO"
    
    echo "=== Installation des Certificats Cisco Umbrella ==="
    echo "Source de Certificat : $cert_source"
    echo "Administrateur : $admin_user"
    echo ""
    
    local cert_files=()
    
    case "$cert_source" in
        "auto")
            # Télécharger les certificats depuis Cisco (nécessite authentification)
            echo "Téléchargement des derniers certificats racine Cisco Umbrella..."
            
            # Note : En production, ceux-ci seraient téléchargés depuis le portail Cisco
            # Pour cet exemple, nous vérifierons les certificats pré-téléchargés
            if [[ -f "$CERTS_DIR/cisco_umbrella_root.pem" ]]; then
                cert_files+=("$CERTS_DIR/cisco_umbrella_root.pem")
            else
                echo "⚠️  Fichiers de certificats non trouvés dans $CERTS_DIR"
                echo "Veuillez télécharger les certificats depuis le portail Cisco Umbrella :"
                echo "Deployments > Configuration > Root Certificate"
                return 1
            fi
            ;;
        "local")
            # Utiliser les certificats fournis localement
            cert_files=($(find "$CERTS_DIR" -name "*.pem" -o -name "*.crt" -o -name "*.cer"))
            ;;
        *)
            # Fichier de certificat spécifique
            if [[ -f "$cert_source" ]]; then
                cert_files=("$cert_source")
            else
                echo "Fichier de certificat non trouvé : $cert_source"
                return 1
            fi
            ;;
    esac
    
    if [[ ${#cert_files[@]} -eq 0 ]]; then
        echo "Aucun fichier de certificat trouvé"
        return 1
    fi
    
    # Installer les certificats
    local installed_count=0
    for cert_file in "${cert_files[@]}"; do
        echo "Installation du certificat : $(basename "$cert_file")"
        
        # Vérifier le certificat avant installation
        if openssl x509 -in "$cert_file" -text -noout &>/dev/null; then
            # Installer dans le trousseau système
            if security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain "$cert_file"; then
                echo "✅ Certificat installé avec succès"
                installed_count=$((installed_count + 1))
                log_operation "INFO" "Certificat installé : $(basename "$cert_file")"
            else
                echo "❌ Échec d'installation du certificat : $(basename "$cert_file")"
                log_operation "ERROR" "Échec d'installation du certificat : $(basename "$cert_file")"
            fi
        else
            echo "❌ Format de certificat invalide : $(basename "$cert_file")"
            log_operation "ERROR" "Format de certificat invalide : $(basename "$cert_file")"
        fi
    done
    
    echo ""
    echo "Installation de certificat terminée : $installed_count/${#cert_files[@]} réussies"
    
    if [[ $installed_count -gt 0 ]]; then
        log_security_event "CERTS_INSTALLED" "count=$installed_count" "INFO"
        return 0
    else
        log_security_event "CERT_INSTALL_FAILED" "all_failed=true" "ERROR"
        return 1
    fi
}

# Surveiller la santé du service Cisco Umbrella
monitor_umbrella_health() {
    local check_type="${1:-basic}"
    local admin_user=$(whoami)
    
    echo "=== Surveillance Santé Cisco Umbrella ==="
    echo "Type de Vérification : $check_type"
    echo "Surveillant : $admin_user"
    echo ""
    
    local health_status="HEALTHY"
    local issues=()
    
    # Vérifier si le fichier de configuration existe et est valide
    if [[ ! -f "$UMBRELLA_CONFIG" ]]; then
        health_status="CRITICAL"
        issues+=("Fichier de configuration manquant")
    elif ! plutil -lint "$UMBRELLA_CONFIG" &>/dev/null; then
        health_status="CRITICAL"
        issues+=("Fichier de configuration corrompu")
    fi
    
    # Vérifier si le processus Umbrella est en cours d'exécution
    if ! pgrep -f "Umbrella" &>/dev/null; then
        health_status="WARNING"
        issues+=("Client Umbrella non en cours d'exécution")
    fi
    
    # Vérifier la résolution DNS via Umbrella
    echo "Test de résolution DNS via Cisco Umbrella..."
    local test_domains=("cisco.com" "umbrella.com" "google.com")
    local dns_failures=0
    
    for domain in "${test_domains[@]}"; do
        if timeout "$HEALTH_CHECK_TIMEOUT" nslookup "$domain" &>/dev/null; then
            echo "✅ Résolution DNS réussie : $domain"
        else
            echo "❌ Résolution DNS échouée : $domain"
            dns_failures=$((dns_failures + 1))
        fi
    done
    
    if [[ $dns_failures -gt 0 ]]; then
        health_status="WARNING"
        issues+=("Problèmes de résolution DNS ($dns_failures échecs)")
    fi
    
    # Vérifier la validité des certificats
    echo ""
    echo "Vérification des certificats Cisco Umbrella..."
    local expired_certs=0
    
    # Obtenir les certificats liés à Umbrella depuis le trousseau système
    local umbrella_certs=$(security find-certificate -a -c "Cisco" /Library/Keychains/System.keychain 2>/dev/null | grep "alis" | wc -l)
    
    if [[ $umbrella_certs -eq 0 ]]; then
        health_status="WARNING"
        issues+=("Aucun certificat Cisco trouvé")
    else
        echo "✅ Trouvé $umbrella_certs certificats Cisco"
    fi
    
    # Vérifications avancées
    if [[ "$check_type" == "comprehensive" ]]; then
        echo ""
        echo "Exécution des vérifications de santé complètes..."
        
        # Vérifier le fichier log pour les erreurs
        if [[ -f "/Library/Logs/OpenDNSRoamingClient.log" ]]; then
            local recent_errors=$(tail -100 "/Library/Logs/OpenDNSRoamingClient.log" 2>/dev/null | grep -i "error" | wc -l)
            if [[ $recent_errors -gt 5 ]]; then
                health_status="WARNING"
                issues+=("Nombre élevé d'erreurs dans les logs ($recent_errors)")
            fi
        fi
        
        # Vérifier la connectivité réseau vers les serveurs Umbrella
        local umbrella_servers=("208.67.222.222" "208.67.220.220")
        for server in "${umbrella_servers[@]}"; do
            if timeout 5 ping -c 1 "$server" &>/dev/null; then
                echo "✅ Connectivité vers le serveur Umbrella : $server"
            else
                echo "❌ Impossible de joindre le serveur Umbrella : $server"
                health_status="WARNING"
                issues+=("Problèmes de connectivité vers $server")
            fi
        done
    fi
    
    # Générer le rapport de santé
    echo ""
    echo "=== Rapport d'État de Santé ==="
    echo "État Global : $health_status"
    echo "Horodatage : $(date)"
    
    if [[ ${#issues[@]} -gt 0 ]]; then
        echo "Problèmes Trouvés :"
        printf '  - %s\n' "${issues[@]}"
    else
        echo "✅ Tous les systèmes opérationnels"
    fi
    
    # Enregistrer l'état de santé
    log_operation "INFO" "Vérification de santé terminée : $health_status (${#issues[@]} problèmes)"
    log_security_event "HEALTH_CHECK" "status=$health_status,issues=${#issues[@]}" "INFO"
    
    # Retourner le code de sortie approprié
    case "$health_status" in
        "HEALTHY") return 0 ;;
        "WARNING") return 1 ;;
        "CRITICAL") return 2 ;;
        *) return 3 ;;
    esac
}

# Générer un rapport de déploiement Umbrella
generate_umbrella_report() {
    local report_type="${1:-summary}"
    local admin_user=$(whoami)
    local report_file="/var/reports/umbrella_report_$(date +%Y%m%d_%H%M%S).txt"
    
    mkdir -p "$(dirname "$report_file")"
    
    log_security_event "REPORT_GENERATION" "type=$report_type" "INFO"
    
    {
        echo "Rapport de Déploiement Cisco Umbrella MacFleet"
        echo "=============================================="
        echo "Type de Rapport : $report_type"
        echo "Généré : $(date)"
        echo "Généré Par : $admin_user"
        echo "Nom d'hôte : $(hostname)"
        echo ""
        
        case "$report_type" in
            "summary")
                echo "== Résumé de Déploiement =="
                echo "Organisation : $ORGANIZATION_NAME"
                echo "Mode de Déploiement : $DEPLOYMENT_MODE"
                echo "Fichier de Configuration : $UMBRELLA_CONFIG"
                
                if [[ -f "$UMBRELLA_CONFIG" ]]; then
                    echo "État de Configuration : Déployé"
                    local config_date=$(stat -f %Sm "$UMBRELLA_CONFIG")
                    echo "Dernière Modification : $config_date"
                else
                    echo "État de Configuration : Non Déployé"
                fi
                
                # État du client
                if pgrep -f "Umbrella" &>/dev/null; then
                    echo "État du Client : En cours d'exécution"
                else
                    echo "État du Client : Non en cours d'exécution"
                fi
                ;;
            "security")
                echo "== Évaluation de Sécurité =="
                echo "Fonctionnalités de Sécurité Activées :"
                
                if [[ -f "$UMBRELLA_CONFIG" ]]; then
                    local malware_blocking=$(plutil -extract BlockMalware xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Activé" || echo "Désactivé")
                    local phishing_blocking=$(plutil -extract BlockPhishing xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Activé" || echo "Désactivé")
                    local content_filtering=$(plutil -extract ContentFiltering xml1 -o - "$UMBRELLA_CONFIG" 2>/dev/null | grep -o "<true/>" && echo "Activé" || echo "Désactivé")
                    
                    echo "  Blocage Malware : $malware_blocking"
                    echo "  Blocage Phishing : $phishing_blocking"
                    echo "  Filtrage Contenu : $content_filtering"
                else
                    echo "  Configuration non disponible pour analyse"
                fi
                
                # État des certificats
                local cisco_certs=$(security find-certificate -a -c "Cisco" /Library/Keychains/System.keychain 2>/dev/null | grep "alis" | wc -l)
                echo "  Certificats Cisco Installés : $cisco_certs"
                ;;
            "audit")
                echo "== Information d'Audit =="
                if [[ -f "$AUDIT_LOG" ]]; then
                    echo "Événements de sécurité récents (10 derniers) :"
                    tail -10 "$AUDIT_LOG"
                else
                    echo "Aucun log d'audit disponible"
                fi
                ;;
        esac
        
        echo ""
        echo "== Détails de Configuration =="
        if [[ -f "$UMBRELLA_CONFIG" ]]; then
            echo "Contenu du fichier de configuration :"
            cat "$UMBRELLA_CONFIG"
        else
            echo "Aucun fichier de configuration trouvé"
        fi
        
    } > "$report_file"
    
    echo "Rapport de déploiement Umbrella généré : $report_file"
    log_operation "INFO" "Rapport Umbrella généré : $report_file"
}

# Définir les paramètres spécifiques à l'organisation
set_organization_params() {
    local api_fingerprint="$1"
    local api_org_id="$2"
    local api_user_id="$3"
    
    if [[ -z "$api_fingerprint" || -z "$api_org_id" || -z "$api_user_id" ]]; then
        echo "Usage : set_organization_params <api_fingerprint> <api_org_id> <api_user_id>"
        echo ""
        echo "Ces paramètres peuvent être obtenus depuis :"
        echo "Portail Cisco Umbrella > Deployments > Core Identities > Roaming Computers"
        return 1
    fi
    
    UMBRELLA_CONFIG_PARAMS["APIFingerprint"]="$api_fingerprint"
    UMBRELLA_CONFIG_PARAMS["APIOrganizationID"]="$api_org_id"
    UMBRELLA_CONFIG_PARAMS["APIUserID"]="$api_user_id"
    
    echo "Paramètres d'organisation mis à jour avec succès"
    log_security_event "ORG_PARAMS_SET" "org_id=$api_org_id" "INFO"
}

# Fonction principale de gestion Cisco Umbrella
main() {
    local action="${1:-help}"
    
    case "$action" in
        "configure")
            local user_profile="${2:-standard}"
            local custom_settings="$3"
            
            generate_umbrella_config "$user_profile" "$custom_settings"
            ;;
        "install-certs")
            local cert_source="${2:-auto}"
            
            install_umbrella_certificates "$cert_source"
            ;;
        "health")
            local check_type="${2:-basic}"
            
            monitor_umbrella_health "$check_type"
            ;;
        "report")
            local report_type="${2:-summary}"
            
            generate_umbrella_report "$report_type"
            ;;
        "set-params")
            local api_fingerprint="$2"
            local api_org_id="$3"
            local api_user_id="$4"
            
            set_organization_params "$api_fingerprint" "$api_org_id" "$api_user_id"
            ;;
        "deploy")
            local user_profile="${2:-standard}"
            
            echo "=== Déploiement Complet Cisco Umbrella ==="
            echo "Démarrage du déploiement complet..."
            echo ""
            
            # Étape 1 : Générer la configuration
            if generate_umbrella_config "$user_profile"; then
                echo "✅ Déploiement de configuration réussi"
            else
                echo "❌ Déploiement de configuration échoué"
                exit 1
            fi
            
            echo ""
            
            # Étape 2 : Installer les certificats
            if install_umbrella_certificates "auto"; then
                echo "✅ Installation de certificats réussie"
            else
                echo "⚠️  Installation de certificats a eu des problèmes"
            fi
            
            echo ""
            
            # Étape 3 : Vérification de santé
            echo "Exécution de la vérification de santé post-déploiement..."
            monitor_umbrella_health "basic"
            
            echo ""
            echo "🎉 Déploiement Cisco Umbrella terminé !"
            echo "Étapes suivantes :"
            echo "1. Installer le fichier PKG Cisco Umbrella via JAMF ou installation manuelle"
            echo "2. Vérifier que le client fonctionne et est connecté"
            echo "3. Tester le filtrage DNS et les fonctionnalités de sécurité"
            ;;
        "help"|*)
            echo "$SCRIPT_NAME v$VERSION"
            echo "Gestion Entreprise du Client Itinérant Cisco Umbrella"
            echo ""
            echo "Usage : $0 <action> [options]"
            echo ""
            echo "Actions :"
            echo "  configure [profil]                         - Générer la configuration Umbrella"
            echo "  install-certs [source]                     - Installer les certificats Cisco"
            echo "  health [type]                              - Surveiller la santé Umbrella"
            echo "  report [type]                              - Générer des rapports de déploiement"
            echo "  set-params <fingerprint> <org_id> <user_id> - Définir les paramètres d'organisation"
            echo "  deploy [profil]                            - Workflow de déploiement complet"
            echo "  help                                       - Afficher ce message d'aide"
            echo ""
            echo "Profils Utilisateur :"
            echo "  executive   - Sécurité élevée, blocage minimal"
            echo "  standard    - Sécurité équilibrée et utilisabilité (défaut)"
            echo "  guest       - Sécurité basique, blocage étendu"
            echo "  developer   - Sécurité moyenne, blocage minimal"
            echo "  kiosk       - Sécurité maximale, blocage étendu"
            echo ""
            echo "Sources de Certificats :"
            echo "  auto        - Télécharger depuis Cisco (défaut)"
            echo "  local       - Utiliser les certificats dans $CERTS_DIR"
            echo "  <fichier>   - Fichier de certificat spécifique"
            echo ""
            echo "Types de Vérification de Santé :"
            echo "  basic       - Vérifications de connectivité et configuration de base"
            echo "  comprehensive - Surveillance étendue et diagnostics"
            echo ""
            echo "Types de Rapport :"
            echo "  summary     - Aperçu du déploiement (défaut)"
            echo "  security    - Analyse de configuration de sécurité"
            echo "  audit       - Piste d'audit et événements"
            echo ""
            echo "Fonctionnalités :"
            echo "  • Déploiement automatisé du client Cisco Umbrella"
            echo "  • Configuration de sécurité basée sur les profils"
            echo "  • Gestion des certificats d'entreprise"
            echo "  • Surveillance de santé en temps réel et diagnostics"
            echo "  • Journalisation d'audit complète et conformité"
            echo "  • Intégration avec l'infrastructure de sécurité MacFleet"
            echo "  • Protection avancée contre les menaces et filtrage DNS"
            ;;
    esac
}

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

Commandes de Référence Rapide

Configuration Initiale

# Définir les paramètres d'organisation (obtenus depuis le tableau de bord Cisco)
./umbrella_manager.sh set-params "votre_api_fingerprint" "votre_org_id" "votre_user_id"

# Déployer avec profil standard
./umbrella_manager.sh deploy standard

# Déployer avec profil executive
./umbrella_manager.sh deploy executive

Gestion de Configuration

# Générer la configuration pour différents profils utilisateur
./umbrella_manager.sh configure standard
./umbrella_manager.sh configure executive
./umbrella_manager.sh configure guest
./umbrella_manager.sh configure developer
./umbrella_manager.sh configure kiosk

Gestion de Certificats

# Installer les certificats automatiquement
./umbrella_manager.sh install-certs auto

# Installer depuis un répertoire local
./umbrella_manager.sh install-certs local

# Installer un fichier de certificat spécifique
./umbrella_manager.sh install-certs /path/to/cisco_cert.pem

Surveillance de Santé

# Vérification de santé basique
./umbrella_manager.sh health

# Vérification de santé complète
./umbrella_manager.sh health comprehensive

Opérations de Rapport

# Générer un rapport résumé
./umbrella_manager.sh report

# Générer une évaluation de sécurité
./umbrella_manager.sh report security

# Générer un rapport d'audit
./umbrella_manager.sh report audit

Exemples d'Intégration

Intégration JAMF Pro

#!/bin/bash

# Script JAMF Pro pour déploiement Cisco Umbrella
# Paramètres : $4 = profil_utilisateur, $5 = api_fingerprint, $6 = api_org_id, $7 = api_user_id

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

# Télécharger le gestionnaire Umbrella s'il n'est pas présent
if [[ ! -f "/usr/local/bin/macfleet_umbrella_manager.sh" ]]; then
    curl -o "/usr/local/bin/macfleet_umbrella_manager.sh" \
         "https://scripts.macfleet.com/umbrella_manager.sh"
    chmod +x "/usr/local/bin/macfleet_umbrella_manager.sh"
fi

# Définir les paramètres d'organisation
/usr/local/bin/macfleet_umbrella_manager.sh set-params \
    "$API_FINGERPRINT" "$API_ORG_ID" "$API_USER_ID"

# Déployer la configuration Umbrella
/usr/local/bin/macfleet_umbrella_manager.sh deploy "$PROFIL_UTILISATEUR"

# Rapporter le statut à JAMF
if [[ $? -eq 0 ]]; then
    echo "Cisco Umbrella déployé avec succès"
    exit 0
else
    echo "Déploiement Cisco Umbrella échoué"
    exit 1
fi

Fonctionnalités de Sécurité Avancées

Intégration d'Intelligence des Menaces

# Surveillance de sécurité renforcée avec intelligence des menaces
enhanced_threat_monitoring() {
    local threat_feeds=("malware" "phishing" "botnet" "ransomware")
    
    echo "=== Surveillance Avancée des Menaces ==="
    
    for feed in "${threat_feeds[@]}"; do
        local blocked_count=$(grep -c "$feed" /Library/Logs/OpenDNSRoamingClient.log 2>/dev/null || echo 0)
        echo "Menaces $feed bloquées : $blocked_count"
        
        if [[ $blocked_count -gt 100 ]]; then
            log_security_event "HIGH_THREAT_ACTIVITY" "feed=$feed,count=$blocked_count" "WARNING"
        fi
    done
}

Meilleures Pratiques

  1. Sécuriser les identifiants API et utiliser des variables d'environnement pour les données sensibles
  2. Implémenter des configurations basées sur les profils pour différents types d'utilisateurs
  3. Activer la journalisation complète pour la surveillance de sécurité et la conformité
  4. Automatiser la gestion et le renouvellement des certificats
  5. Surveiller la santé du service en continu avec alertes
  6. Intégrer avec les systèmes SIEM pour la surveillance de sécurité centralisée
  7. Mises à jour régulières des politiques basées sur l'intelligence des menaces
  8. Tester le filtrage DNS et les fonctionnalités de sécurité après déploiement

Ce système de gestion Cisco Umbrella entreprise fournit une protection DNS de sécurité complète avec déploiement automatisé, capacités de surveillance et contrôles de niveau entreprise pour une gestion de sécurité MacFleet efficace.

Gestion et Sécurité des Extensions Chrome sur macOS

Gérez et sécurisez les extensions Google Chrome sur vos appareils MacFleet avec des outils complets de découverte, d'analyse et d'application de politiques. Ce tutoriel couvre l'énumération des extensions, l'évaluation de sécurité et la gestion de navigateur d'entreprise.

Comprendre la Gestion des Extensions Chrome

Les extensions Chrome améliorent les fonctionnalités du navigateur mais peuvent introduire des risques de sécurité. La gestion d'entreprise inclut :

  • Découverte d'Extensions - Identifier toutes les extensions installées sur les appareils
  • Analyse de Sécurité - Évaluer les permissions et risques des extensions
  • Application de Politiques - Contrôler quelles extensions sont autorisées
  • Surveillance de Conformité - Assurer l'adhésion aux politiques de sécurité

Préoccupations de Sécurité des Extensions

Les extensions de navigateur peuvent poser des risques de sécurité d'entreprise :

  • Accès aux Données - Les extensions peuvent lire les données de navigation et informations personnelles
  • Requêtes Réseau - Certaines extensions communiquent avec des serveurs externes
  • Extensions Malveillantes - Extensions non autorisées ou compromises
  • Impact sur la Productivité - Extensions non professionnelles affectant l'efficacité au travail
  • Violations de Conformité - Extensions en conflit avec les exigences réglementaires

Découverte de Base des Extensions Chrome

Lister Toutes les Extensions Installées

#!/bin/bash

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

echo "Extensions Chrome pour l'utilisateur : $currentUser"
echo "======================================="

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

Découverte d'Extensions Améliorée avec Détails

#!/bin/bash

# Découverte d'extensions Chrome améliorée avec métadonnées
discover_chrome_extensions() {
    local user_name="${1:-$(ls -l /dev/console | awk '{print $3}')}"
    local detailed="${2:-false}"
    
    local chrome_dir="/Users/$user_name/Library/Application Support/Google/Chrome"
    local extensions_dir="$chrome_dir/Default/Extensions"
    
    if [[ ! -d "$extensions_dir" ]]; then
        echo "Répertoire des extensions Chrome non trouvé pour l'utilisateur : $user_name"
        return 1
    fi
    
    echo "=== Découverte des Extensions Chrome ==="
    echo "Utilisateur : $user_name"
    echo "Répertoire des Extensions : $extensions_dir"
    echo "Date de Découverte : $(date)"
    echo ""
    
    local extension_count=0
    local extensions_found=()
    
    # Trouver tous les fichiers manifest.json
    while IFS= read -r -d '' manifest_path; do
        ((extension_count++))
        
        local extension_id=$(basename "$(dirname "$(dirname "$manifest_path")")")
        local version_dir=$(dirname "$manifest_path")
        local version=$(basename "$version_dir")
        
        extensions_found+=("$extension_id:$version:$manifest_path")
        
        if [[ "$detailed" == "true" ]]; then
            echo "--- Extension $extension_count ---"
            echo "ID : $extension_id"
            echo "Version : $version"
            echo "Manifest : $manifest_path"
            
            # Extraire le nom et la description de l'extension du manifest
            if [[ -f "$manifest_path" ]]; then
                local name=$(python3 -c "import json, sys; data=json.load(open('$manifest_path')); print(data.get('name', 'Inconnu'))" 2>/dev/null || echo "Inconnu")
                local description=$(python3 -c "import json, sys; data=json.load(open('$manifest_path')); print(data.get('description', 'Aucune description'))" 2>/dev/null || echo "Aucune description")
                
                echo "Nom : $name"
                echo "Description : $description"
            fi
            echo ""
        else
            echo "$extension_id"
        fi
        
    done < <(find "$extensions_dir" -name 'manifest.json' -print0 2>/dev/null)
    
    echo ""
    echo "Total d'extensions trouvées : $extension_count"
    
    return 0
}

# Exemples d'utilisation
discover_chrome_extensions "$(whoami)" "true"
discover_chrome_extensions "$(whoami)" "false"

Vérifier l'Installation d'une Extension Spécifique

#!/bin/bash

# Vérifier si une extension spécifique est installée
check_extension_installed() {
    local extension_id="$1"
    local user_name="${2:-$(ls -l /dev/console | cut -d " " -f 4)}"
    
    if [[ -z "$extension_id" ]]; then
        echo "Usage : check_extension_installed <extension_id> [nom_utilisateur]"
        echo "Exemple : check_extension_installed nmmhkkegccagdldgiimedpiccmgmieda"
        return 1
    fi
    
    local extension_path="/Users/$user_name/Library/Application Support/Google/Chrome/Default/Extensions/$extension_id"
    
    if [[ -d "$extension_path" ]]; then
        echo "<result>L'extension $extension_id est installée.</result>"
        
        # Obtenir les détails de l'extension si le manifest existe
        local manifest_files=("$extension_path"/*/manifest.json)
        if [[ -f "${manifest_files[0]}" ]]; then
            local manifest_path="${manifest_files[0]}"
            local version=$(basename "$(dirname "$manifest_path")")
            
            echo "Détails de l'Extension :"
            echo "- ID : $extension_id"
            echo "- Version : $version"
            echo "- Chemin : $extension_path"
            
            # Extraire le nom du manifest
            local name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Inconnu'))" 2>/dev/null || echo "Inconnu")
            echo "- Nom : $name"
        fi
        
        return 0
    else
        echo "<result>L'extension $extension_id n'est pas installée.</result>"
        return 1
    fi
}

# Exemples d'utilisation
check_extension_installed "nmmhkkegccagdldgiimedpiccmgmieda"
check_extension_installed "cjpalhdlnbpafiamejdnhcphjbkeiagm"

Analyse Avancée des Extensions

Analyse de Sécurité Complète des Extensions

#!/bin/bash

# Analyse de sécurité complète des extensions Chrome
analyze_extension_security() {
    local extension_id="$1"
    local user_name="${2:-$(ls -l /dev/console | awk '{print $3}')}"
    
    if [[ -z "$extension_id" ]]; then
        echo "Usage : analyze_extension_security <extension_id> [nom_utilisateur]"
        return 1
    fi
    
    local extension_path="/Users/$user_name/Library/Application Support/Google/Chrome/Default/Extensions/$extension_id"
    
    if [[ ! -d "$extension_path" ]]; then
        echo "Extension $extension_id non trouvée pour l'utilisateur $user_name"
        return 1
    fi
    
    echo "=== Analyse de Sécurité de l'Extension ==="
    echo "ID Extension : $extension_id"
    echo "Utilisateur : $user_name"
    echo "Date d'Analyse : $(date)"
    echo ""
    
    # Trouver le fichier manifest
    local manifest_files=("$extension_path"/*/manifest.json)
    if [[ ! -f "${manifest_files[0]}" ]]; then
        echo "Fichier manifest non trouvé pour l'extension $extension_id"
        return 1
    fi
    
    local manifest_path="${manifest_files[0]}"
    local version_dir=$(dirname "$manifest_path")
    local version=$(basename "$version_dir")
    
    echo "--- Informations de Base ---"
    echo "Version : $version"
    echo "Chemin d'Installation : $extension_path"
    echo "Manifest : $manifest_path"
    
    # Analyser le manifest pour l'analyse de sécurité
    if command -v python3 >/dev/null 2>&1; then
        echo ""
        echo "--- Métadonnées de l'Extension ---"
        
        # Extraire les informations de base
        local name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Inconnu'))" 2>/dev/null || echo "Inconnu")
        local description=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('description', 'Aucune description'))" 2>/dev/null || echo "Aucune description")
        local manifest_version=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('manifest_version', 'Inconnu'))" 2>/dev/null || echo "Inconnu")
        
        echo "Nom : $name"
        echo "Description : $description"
        echo "Version Manifest : $manifest_version"
        
        # Analyse de sécurité
        echo ""
        echo "--- Analyse de Sécurité ---"
        
        # Vérifier les permissions
        local permissions=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    perms = data.get('permissions', [])
    for perm in perms:
        print(f'  - {perm}')
except:
    print('  - Erreur lors de la lecture des permissions')
" 2>/dev/null)
        
        if [[ -n "$permissions" ]]; then
            echo "Permissions :"
            echo "$permissions"
        else
            echo "Permissions : Aucune déclarée"
        fi
        
        # Vérifier les permissions d'hôte
        local host_permissions=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    hosts = data.get('host_permissions', [])
    if not hosts:
        hosts = data.get('permissions', [])
        hosts = [h for h in hosts if h.startswith('http') or '*' in h]
    for host in hosts:
        print(f'  - {host}')
except:
    print('  - Erreur lors de la lecture des permissions d\'hôte')
" 2>/dev/null)
        
        if [[ -n "$host_permissions" ]]; then
            echo "Permissions d'Hôte :"
            echo "$host_permissions"
        else
            echo "Permissions d'Hôte : Aucune déclarée"
        fi
        
        # Vérifier les scripts de contenu
        local content_scripts=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    scripts = data.get('content_scripts', [])
    if scripts:
        print('Scripts de contenu détectés :')
        for i, script in enumerate(scripts):
            matches = script.get('matches', [])
            print(f'  Script {i+1}: {matches}')
    else:
        print('Aucun script de contenu')
except:
    print('Erreur lors de la lecture des scripts de contenu')
" 2>/dev/null)
        
        echo "Scripts de Contenu : $content_scripts"
        
        # Évaluation des risques
        echo ""
        echo "--- Évaluation des Risques ---"
        assess_extension_risk "$manifest_path"
        
    else
        echo "Python3 non disponible - analyse limitée"
    fi
    
    # Analyse des fichiers
    echo ""
    echo "--- Analyse des Fichiers ---"
    local file_count=$(find "$version_dir" -type f | wc -l)
    local total_size=$(du -sh "$version_dir" | cut -f1)
    
    echo "Total des Fichiers : $file_count"
    echo "Taille Totale : $total_size"
    
    # Vérifier les fichiers suspects
    local js_files=$(find "$version_dir" -name "*.js" | wc -l)
    local html_files=$(find "$version_dir" -name "*.html" | wc -l)
    local json_files=$(find "$version_dir" -name "*.json" | wc -l)
    
    echo "Fichiers JavaScript : $js_files"
    echo "Fichiers HTML : $html_files"
    echo "Fichiers JSON : $json_files"
    
    echo ""
    echo "=== Analyse Terminée ==="
}

# Fonction d'évaluation des risques
assess_extension_risk() {
    local manifest_path="$1"
    local risk_score=0
    local risk_factors=()
    
    # Vérifier les permissions à haut risque
    local high_risk_perms=$(python3 -c "
import json
high_risk = ['activeTab', 'tabs', 'storage', 'cookies', 'history', 'bookmarks', 'downloads', 'management', 'nativeMessaging', 'proxy', 'webRequest', 'webRequestBlocking']
try:
    data = json.load(open('$manifest_path'))
    perms = data.get('permissions', [])
    host_perms = data.get('host_permissions', [])
    all_perms = perms + host_perms
    
    found_high_risk = []
    for perm in all_perms:
        if perm in high_risk:
            found_high_risk.append(perm)
        elif perm == '<all_urls>' or perm == '*://*/*':
            found_high_risk.append('all_urls')
    
    print(','.join(found_high_risk))
except:
    pass
" 2>/dev/null)
    
    if [[ -n "$high_risk_perms" ]]; then
        IFS=',' read -ra PERMS <<< "$high_risk_perms"
        for perm in "${PERMS[@]}"; do
            case "$perm" in
                "all_urls"|"*://*/*")
                    risk_score=$((risk_score + 30))
                    risk_factors+=("Accès à tous les sites web")
                    ;;
                "tabs"|"activeTab")
                    risk_score=$((risk_score + 20))
                    risk_factors+=("Peut accéder aux onglets du navigateur")
                    ;;
                "storage"|"cookies")
                    risk_score=$((risk_score + 15))
                    risk_factors+=("Peut accéder aux données stockées")
                    ;;
                "webRequest"|"webRequestBlocking")
                    risk_score=$((risk_score + 25))
                    risk_factors+=("Peut intercepter les requêtes web")
                    ;;
                "nativeMessaging")
                    risk_score=$((risk_score + 20))
                    risk_factors+=("Peut communiquer avec les applications natives")
                    ;;
                *)
                    risk_score=$((risk_score + 10))
                    risk_factors+=("A la permission $perm")
                    ;;
            esac
        done
    fi
    
    # Déterminer le niveau de risque
    local risk_level
    if [[ $risk_score -ge 50 ]]; then
        risk_level="ÉLEVÉ"
    elif [[ $risk_score -ge 25 ]]; then
        risk_level="MOYEN"
    elif [[ $risk_score -ge 10 ]]; then
        risk_level="FAIBLE"
    else
        risk_level="MINIMAL"
    fi
    
    echo "Niveau de Risque : $risk_level (Score : $risk_score)"
    
    if [[ ${#risk_factors[@]} -gt 0 ]]; then
        echo "Facteurs de Risque :"
        for factor in "${risk_factors[@]}"; do
            echo "  ⚠️ $factor"
        done
    else
        echo "✓ Aucun facteur de risque significatif identifié"
    fi
}

# Usage
analyze_extension_security "nmmhkkegccagdldgiimedpiccmgmieda"

Système de Gestion des Extensions Chrome d'Entreprise

#!/bin/bash

# Outil de Gestion des Extensions Chrome MacFleet
# Découverte, analyse et application de politiques d'extensions de navigateur complètes

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

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

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

# Extensions à risque de sécurité connues
declare -A RISKY_EXTENSIONS=(
    ["adware"]="Variantes AdBlock avec permissions suspectes,Extensions VPN gratuites,Extensions de coupons"
    ["privacy_risk"]="Extensions demandant all_urls,Gestionnaires de mots de passe de développeurs inconnus,Extensions avec messagerie native"
    ["productivity_risk"]="Extensions de réseaux sociaux,Extensions de jeux,Extensions de streaming vidéo"
    ["security_risk"]="Extensions de développeurs inconnus,Extensions avec permissions webRequest,Extensions proxy"
)

# Développeurs d'extensions de confiance
declare -A TRUSTED_DEVELOPERS=(
    ["google"]="Google LLC,Chrome Web Store officiel"
    ["microsoft"]="Microsoft Corporation"
    ["adobe"]="Adobe Inc."
    ["1password"]="AgileBits Inc."
    ["lastpass"]="LogMeIn, Inc."
    ["ublock"]="Raymond Hill (gorhill)"
    ["grammarly"]="Grammarly Inc."
    ["zoom"]="Zoom Video Communications, Inc."
)

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

# Découvrir toutes les extensions Chrome à travers tous les utilisateurs
discover_fleet_extensions() {
    local scan_all_users="${1:-false}"
    local output_format="${2:-detailed}"
    local security_analysis="${3:-true}"
    
    log_action "Démarrage de la découverte d'extensions Chrome à l'échelle de la flotte"
    
    echo "=== Découverte d'Extensions Chrome MacFleet ==="
    echo "Scanner Tous les Utilisateurs : $scan_all_users"
    echo "Format de Sortie : $output_format"
    echo "Analyse de Sécurité : $security_analysis"
    echo ""
    
    local total_extensions=0
    local total_users=0
    local high_risk_extensions=0
    local unknown_extensions=0
    local fleet_data=()
    
    # Déterminer les utilisateurs à scanner
    local users_to_scan=()
    if [[ "$scan_all_users" == "true" ]]; then
        # Obtenir tous les utilisateurs avec des répertoires home
        while IFS= read -r user_dir; do
            local username=$(basename "$user_dir")
            users_to_scan+=("$username")
        done < <(find /Users -maxdepth 1 -type d -not -name "Shared" -not -name "." -not -name ".." | grep -v "/Users$")
    else
        # Utilisateur console actuel seulement
        local current_user=$(ls -l /dev/console | awk '{print $3}')
        users_to_scan=("$current_user")
    fi
    
    # Scanner chaque utilisateur
    for username in "${users_to_scan[@]}"; do
        local chrome_dir="/Users/$username/Library/Application Support/Google/Chrome"
        local extensions_dir="$chrome_dir/Default/Extensions"
        
        if [[ ! -d "$extensions_dir" ]]; then
            continue
        fi
        
        ((total_users++))
        echo "--- Utilisateur : $username ---"
        
        local user_extension_count=0
        
        # Trouver toutes les extensions pour cet utilisateur
        while IFS= read -r -d '' manifest_path; do
            ((total_extensions++))
            ((user_extension_count++))
            
            local extension_id=$(basename "$(dirname "$(dirname "$manifest_path")")")
            local version_dir=$(dirname "$manifest_path")
            local version=$(basename "$version_dir")
            
            # Informations de base de l'extension
            local name="Inconnu"
            local description="Aucune description"
            local risk_level="INCONNU"
            
            if command -v python3 >/dev/null 2>&1; then
                name=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('name', 'Inconnu'))" 2>/dev/null || echo "Inconnu")
                description=$(python3 -c "import json; data=json.load(open('$manifest_path')); print(data.get('description', 'Aucune description'))" 2>/dev/null || echo "Aucune description")
                
                if [[ "$security_analysis" == "true" ]]; then
                    risk_level=$(assess_extension_risk_level "$manifest_path")
                    if [[ "$risk_level" == "ÉLEVÉ" ]]; then
                        ((high_risk_extensions++))
                    fi
                fi
            fi
            
            # Vérifier si l'extension est connue/de confiance
            local trust_status="INCONNU"
            check_extension_trust "$extension_id" "$name" trust_status
            
            if [[ "$trust_status" == "INCONNU" ]]; then
                ((unknown_extensions++))
            fi
            
            # Stocker les données pour le rapport
            fleet_data+=("$username|$extension_id|$name|$version|$risk_level|$trust_status|$description")
            
            # Sortie basée sur le format
            case "$output_format" in
                "detailed")
                    echo "  Extension : $name"
                    echo "    ID : $extension_id"
                    echo "    Version : $version"
                    echo "    Risque : $risk_level"
                    echo "    Confiance : $trust_status"
                    echo ""
                    ;;
                "summary")
                    echo "  $extension_id ($name) - Risque : $risk_level"
                    ;;
                "ids_only")
                    echo "  $extension_id"
                    ;;
            esac
            
        done < <(find "$extensions_dir" -name 'manifest.json' -print0 2>/dev/null)
        
        echo "  Extensions Utilisateur : $user_extension_count"
        echo ""
    done
    
    # Générer le résumé
    echo "=== Résumé de Découverte de Flotte ==="
    echo "Total Utilisateurs Scannés : $total_users"
    echo "Total Extensions Trouvées : $total_extensions"
    echo "Extensions à Haut Risque : $high_risk_extensions"
    echo "Extensions Inconnues : $unknown_extensions"
    echo ""
    
    # Générer les rapports
    if [[ "$output_format" == "json" ]]; then
        generate_json_fleet_report fleet_data
    elif [[ "$output_format" == "csv" ]]; then
        generate_csv_fleet_report fleet_data
    fi
    
    log_action "Découverte d'extensions de flotte terminée : $total_extensions extensions trouvées sur $total_users utilisateurs"
}

# Évaluer le niveau de risque de l'extension
assess_extension_risk_level() {
    local manifest_path="$1"
    local risk_score=0
    
    # Utiliser Python pour analyser le manifest
    risk_score=$(python3 -c "
import json
try:
    data = json.load(open('$manifest_path'))
    score = 0
    
    # Vérifier les permissions
    perms = data.get('permissions', []) + data.get('host_permissions', [])
    
    for perm in perms:
        if perm in ['<all_urls>', '*://*/*']:
            score += 30
        elif perm in ['tabs', 'activeTab']:
            score += 20
        elif perm in ['webRequest', 'webRequestBlocking']:
            score += 25
        elif perm in ['storage', 'cookies', 'history']:
            score += 15
        elif perm in ['nativeMessaging']:
            score += 20
        elif perm.startswith('http'):
            score += 5
    
    print(score)
except:
    print(0)
" 2>/dev/null || echo "0")
    
    if [[ $risk_score -ge 50 ]]; then
        echo "ÉLEVÉ"
    elif [[ $risk_score -ge 25 ]]; then
        echo "MOYEN"
    elif [[ $risk_score -ge 10 ]]; then
        echo "FAIBLE"
    else
        echo "MINIMAL"
    fi
}

# Vérifier le statut de confiance de l'extension
check_extension_trust() {
    local extension_id="$1"
    local extension_name="$2"
    local -n trust_ref=$3
    
    # Vérifier contre la liste blanche
    if [[ -f "$ALLOWLIST_FILE" ]]; then
        if grep -q "$extension_id" "$ALLOWLIST_FILE" 2>/dev/null; then
            trust_ref="APPROUVÉ"
            return
        fi
    fi
    
    # Vérifier contre la liste noire
    if [[ -f "$BLOCKLIST_FILE" ]]; then
        if grep -q "$extension_id" "$BLOCKLIST_FILE" 2>/dev/null; then
            trust_ref="BLOQUÉ"
            return
        fi
    fi
    
    # Vérifier contre les bonnes extensions connues (simplifié)
    case "$extension_id" in
        "cjpalhdlnbpafiamejdnhcphjbkeiagm") # uBlock Origin
            trust_ref="DE CONFIANCE"
            ;;
        "nmmhkkegccagdldgiimedpiccmgmieda") # Google Translate
            trust_ref="DE CONFIANCE"
            ;;
        "gighmmpiobklfepjocnamgkkbiglidom") # AdBlock
            trust_ref="DE CONFIANCE"
            ;;
        *)
            trust_ref="INCONNU"
            ;;
    esac
}

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

        ]
    }
}
EOF
    
    echo "Rapport JSON généré : $report_file"
}

# Fonction d'exécution principale
main() {
    local action="${1:-help}"
    local param1="${2:-}"
    local param2="${3:-}"
    local param3="${4:-}"
    local param4="${5:-}"
    
    log_action "=== Gestion des Extensions Chrome MacFleet Démarrée ==="
    log_action "Action : $action"
    
    case "$action" in
        "discover")
            discover_chrome_extensions "${param1:-$(whoami)}" "${param2:-true}"
            ;;
        "check")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 check <extension_id> [nom_utilisateur]"
                exit 1
            fi
            check_extension_installed "$param1" "$param2"
            ;;
        "analyze")
            if [[ -z "$param1" ]]; then
                echo "Usage : $0 analyze <extension_id> [nom_utilisateur]"
                exit 1
            fi
            analyze_extension_security "$param1" "$param2"
            ;;
        "fleet")
            discover_fleet_extensions "${param1:-false}" "${param2:-detailed}" "${param3:-true}"
            ;;
        "help")
            echo "Usage : $0 [action] [options...]"
            echo "Actions :"
            echo "  discover [nom_utilisateur] [détaillé] - Découvrir les extensions pour l'utilisateur"
            echo "  check <extension_id> [nom_utilisateur] - Vérifier si l'extension est installée"
            echo "  analyze <extension_id> [nom_utilisateur] - Analyser la sécurité de l'extension"
            echo "  fleet [tous_utilisateurs] [format] [sécurité] - Découverte à l'échelle de la flotte"
            echo "  help - Afficher cette aide"
            echo ""
            echo "Politiques : ${!EXTENSION_POLICIES[*]}"
            ;;
        *)
            log_action "ERREUR : Action inconnue : $action"
            echo "Utilisez '$0 help' pour les informations d'utilisation"
            exit 1
            ;;
    esac
    
    log_action "=== Gestion des extensions Chrome terminée ==="
}

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

Notes Importantes

  • Les ID d'extensions sont des chaînes de 32 caractères identifiant uniquement chaque extension
  • Les fichiers manifest contiennent les métadonnées d'extension et les exigences de permissions
  • L'analyse de sécurité devrait se concentrer sur les permissions et l'accès aux données
  • Les politiques d'entreprise devraient équilibrer fonctionnalité et exigences de sécurité
  • La surveillance régulière aide à détecter les extensions non autorisées ou risquées
  • La formation des utilisateurs est essentielle pour la sensibilisation à la sécurité des extensions