Gestion de Lancement Automatique d'Applications sur macOS
Optimisez la productivité d'entreprise en lançant automatiquement les applications essentielles à la connexion utilisateur sur vos appareils MacFleet. Ce tutoriel couvre la configuration LaunchAgent, la gestion d'applications spécifiques aux utilisateurs, la validation de sécurité et les stratégies de déploiement centralisées.
Comprendre les Mécanismes de Lancement d'Applications macOS
macOS fournit plusieurs mécanismes pour le lancement automatique d'applications :
- LaunchAgents - Applications spécifiques à l'utilisateur qui se lancent à la connexion
- LaunchDaemons - Services système qui démarrent au boot
- Éléments de Connexion - Applications configurées par l'utilisateur dans Préférences Système
- Configurations MDM - Configurations de lancement gérées par l'entreprise
Lancement Automatique d'Application Basique
Configuration Simple de Lancement d'Application
#!/bin/bash
# Configuration basique de lancement d'application pour une seule application
APP_NAME="Messages"
PLIST_NAME="com.${APP_NAME}.plist"
LAUNCH_AGENTS_DIR="/Library/LaunchAgents"
# Créer le plist LaunchAgent
cat > "${LAUNCH_AGENTS_DIR}/${PLIST_NAME}" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<false/>
<key>Label</key>
<string>${PLIST_NAME}</string>
<key>Program</key>
<string>/System/Applications/${APP_NAME}.app/Contents/MacOS/${APP_NAME}</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
EOF
echo "LaunchAgent créé pour ${APP_NAME}"
Lancement d'Application Amélioré avec Validation
#!/bin/bash
# Lancement d'application amélioré avec validation
setup_app_launch() {
local app_name="$1"
local app_path="$2"
local plist_name="com.macfleet.${app_name}.plist"
echo "Configuration du lancement automatique pour : $app_name"
# Valider que l'application existe
if [[ ! -d "$app_path" ]]; then
echo "Erreur : Application non trouvée à $app_path"
return 1
fi
# Valider l'exécutable
local executable_path="${app_path}/Contents/MacOS/${app_name}"
if [[ ! -x "$executable_path" ]]; then
echo "Erreur : Exécutable non trouvé ou non exécutable : $executable_path"
return 1
fi
# Créer le LaunchAgent
cat > "/Library/LaunchAgents/${plist_name}" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<false/>
<key>Label</key>
<string>${plist_name}</string>
<key>Program</key>
<string>${executable_path}</string>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>/var/log/macfleet_${app_name}.error.log</string>
<key>StandardOutPath</key>
<string>/var/log/macfleet_${app_name}.out.log</string>
</dict>
</plist>
EOF
echo "LaunchAgent configuré avec succès pour $app_name"
return 0
}
# Exemple d'utilisation
setup_app_launch "Messages" "/System/Applications/Messages.app"
Gestion de Lancement d'Applications d'Entreprise
#!/bin/bash
# Gestion de Lancement d'Applications d'Entreprise MacFleet
# Contrôle centralisé des lancements automatiques d'applications sur les appareils de flotte
# Configuration
LOG_FILE="/var/log/macfleet_app_launch.log"
CONFIG_DIR="/etc/macfleet/app_launch"
LAUNCH_AGENTS_DIR="/Library/LaunchAgents"
USER_LAUNCH_AGENTS_DIR="~/Library/LaunchAgents"
BACKUP_DIR="/var/backups/launch_agents"
# Base de données de configuration d'applications
declare -A ENTERPRISE_APPS=(
["suite_productivite"]="Slack,Microsoft Teams,Notion,1Password 7 - Password Manager"
["outils_developpement"]="Xcode,Terminal,Visual Studio Code,Docker Desktop"
["suite_design"]="Adobe Photoshop 2023,Sketch,Figma,Adobe Illustrator 2023"
["communication"]="Messages,Mail,Zoom,Microsoft Outlook"
["outils_securite"]="Little Snitch 5,1Password 7 - Password Manager,Malwarebytes Anti-Malware"
)
# Configurations de profils utilisateur
declare -A USER_PROFILES=(
["developpeur"]="outils_developpement,communication,outils_securite"
["designer"]="suite_design,communication,suite_productivite"
["manager"]="suite_productivite,communication"
["securite"]="outils_securite,communication,suite_productivite"
["defaut"]="communication"
)
# Fonction de journalisation
log_action() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Créer les répertoires nécessaires
setup_directories() {
for dir in "$CONFIG_DIR" "$BACKUP_DIR"; do
if [[ ! -d "$dir" ]]; then
mkdir -p "$dir"
log_action "Répertoire créé : $dir"
fi
done
}
# Valider le chemin et l'exécutable de l'application
validate_application() {
local app_name="$1"
local app_path=""
log_action "Validation de l'application : $app_name"
# Chemins d'applications communs à vérifier
local search_paths=(
"/Applications"
"/System/Applications"
"/Applications/Utilities"
"/System/Applications/Utilities"
)
# Trouver l'application
for base_path in "${search_paths[@]}"; do
local potential_path="${base_path}/${app_name}.app"
if [[ -d "$potential_path" ]]; then
app_path="$potential_path"
break
fi
done
if [[ -z "$app_path" ]]; then
log_action "❌ Application non trouvée : $app_name"
return 1
fi
# Valider l'exécutable
local executable_path="${app_path}/Contents/MacOS/${app_name}"
if [[ ! -x "$executable_path" ]]; then
# Essayer un nom d'exécutable alternatif (certaines apps utilisent des noms différents)
local info_plist="${app_path}/Contents/Info.plist"
if [[ -f "$info_plist" ]]; then
local bundle_executable
bundle_executable=$(defaults read "$info_plist" CFBundleExecutable 2>/dev/null)
if [[ -n "$bundle_executable" ]]; then
executable_path="${app_path}/Contents/MacOS/${bundle_executable}"
fi
fi
if [[ ! -x "$executable_path" ]]; then
log_action "❌ Exécutable non trouvé ou non exécutable : $executable_path"
return 1
fi
fi
log_action "✅ Application validée : $app_name à $app_path"
echo "$app_path"
return 0
}
# Créer le plist LaunchAgent pour l'application
create_launch_agent() {
local app_name="$1"
local app_path="$2"
local user_specific="${3:-false}"
local delay="${4:-0}"
local plist_name="com.macfleet.${app_name// /_}.plist"
local target_dir="$LAUNCH_AGENTS_DIR"
if [[ "$user_specific" == "true" ]]; then
target_dir="$USER_LAUNCH_AGENTS_DIR"
fi
log_action "Création du LaunchAgent pour : $app_name"
# Obtenir le chemin de l'exécutable
local executable_path="${app_path}/Contents/MacOS/${app_name}"
local info_plist="${app_path}/Contents/Info.plist"
if [[ -f "$info_plist" ]]; then
local bundle_executable
bundle_executable=$(defaults read "$info_plist" CFBundleExecutable 2>/dev/null)
if [[ -n "$bundle_executable" ]]; then
executable_path="${app_path}/Contents/MacOS/${bundle_executable}"
fi
fi
# Créer le contenu du plist
cat > "${target_dir}/${plist_name}" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${plist_name}</string>
<key>Program</key>
<string>${executable_path}</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<false/>
<key>StandardErrorPath</key>
<string>/var/log/macfleet_$(echo "$app_name" | tr ' ' '_').error.log</string>
<key>StandardOutPath</key>
<string>/var/log/macfleet_$(echo "$app_name" | tr ' ' '_').out.log</string>
EOF
# Ajouter un délai si spécifié
if [[ "$delay" -gt 0 ]]; then
cat >> "${target_dir}/${plist_name}" << EOF
<key>StartInterval</key>
<integer>$delay</integer>
EOF
fi
# Ajouter des variables d'environnement pour les applications d'entreprise
cat >> "${target_dir}/${plist_name}" << EOF
<key>EnvironmentVariables</key>
<dict>
<key>MACFLEET_MANAGED</key>
<string>true</string>
<key>ENTERPRISE_MODE</key>
<string>enabled</string>
</dict>
</dict>
</plist>
EOF
# Définir les permissions appropriées
chmod 644 "${target_dir}/${plist_name}"
log_action "✅ LaunchAgent créé : ${plist_name}"
return 0
}
# Supprimer le LaunchAgent pour l'application
remove_launch_agent() {
local app_name="$1"
local user_specific="${2:-false}"
local plist_name="com.macfleet.${app_name// /_}.plist"
local target_dir="$LAUNCH_AGENTS_DIR"
if [[ "$user_specific" == "true" ]]; then
target_dir="$USER_LAUNCH_AGENTS_DIR"
fi
local plist_path="${target_dir}/${plist_name}"
if [[ -f "$plist_path" ]]; then
# Décharger si chargé
launchctl unload "$plist_path" 2>/dev/null || true
# Supprimer le fichier
rm -f "$plist_path"
log_action "✅ LaunchAgent supprimé : $plist_name"
return 0
else
log_action "⚠️ LaunchAgent non trouvé : $plist_name"
return 1
fi
}
# Déployer les applications pour le profil utilisateur
deploy_user_profile() {
local profile_name="$1"
local username="${2:-$(whoami)}"
log_action "Déploiement du profil utilisateur : $profile_name pour l'utilisateur : $username"
# Obtenir la configuration du profil
local profile_config="${USER_PROFILES[$profile_name]}"
if [[ -z "$profile_config" ]]; then
log_action "❌ Profil utilisateur inconnu : $profile_name"
return 1
fi
# Sauvegarder la configuration existante
backup_launch_agents
local success_count=0
local total_count=0
local failed_apps=()
# Traiter chaque suite d'applications dans le profil
IFS=',' read -ra SUITES <<< "$profile_config"
for suite in "${SUITES[@]}"; do
local suite_apps="${ENTERPRISE_APPS[$suite]}"
if [[ -z "$suite_apps" ]]; then
log_action "⚠️ Suite d'applications inconnue : $suite"
continue
fi
# Traiter chaque application dans la suite
IFS=',' read -ra APPS <<< "$suite_apps"
for app in "${APPS[@]}"; do
total_count=$((total_count + 1))
# Valider et déployer l'application
local app_path
if app_path=$(validate_application "$app"); then
if create_launch_agent "$app" "$app_path" false 0; then
success_count=$((success_count + 1))
log_action "✅ Déployé : $app"
else
failed_apps+=("$app")
fi
else
failed_apps+=("$app")
fi
done
done
# Générer le rapport de déploiement
generate_deployment_report "$profile_name" "$username" "$success_count" "$total_count" "${failed_apps[@]}"
log_action "Déploiement de profil terminé : $success_count/$total_count réussi"
return $((total_count - success_count))
}
# Sauvegarder les LaunchAgents existants
backup_launch_agents() {
local backup_timestamp
backup_timestamp=$(date '+%Y%m%d_%H%M%S')
local backup_file="$BACKUP_DIR/launch_agents_backup_$backup_timestamp.tar.gz"
log_action "Création de la sauvegarde LaunchAgents : $backup_file"
if tar -czf "$backup_file" -C /Library LaunchAgents 2>/dev/null; then
log_action "✅ Sauvegarde créée : $backup_file"
return 0
else
log_action "❌ Échec de la sauvegarde"
return 1
fi
}
# Générer le rapport de déploiement
generate_deployment_report() {
local profile_name="$1"
local username="$2"
local success_count="$3"
local total_count="$4"
shift 4
local failed_apps=("$@")
local report_file="$CONFIG_DIR/deployment_report_$(date '+%Y%m%d_%H%M%S').json"
log_action "Génération du rapport de déploiement : $report_file"
cat > "$report_file" << EOF
{
"deployment_metadata": {
"timestamp": "$(date -Iseconds)",
"profile_name": "$profile_name",
"username": "$username",
"hostname": "$(hostname)",
"generator": "MacFleet App Launch Manager"
},
"deployment_summary": {
"total_applications": $total_count,
"successful_deployments": $success_count,
"failed_deployments": $((total_count - success_count)),
"success_rate": $(awk "BEGIN {printf \"%.2f\", ($success_count/$total_count)*100}")
},
"failed_applications": [
EOF
# Ajouter les applications échouées
local first=true
for app in "${failed_apps[@]}"; do
if [[ "$first" == true ]]; then
first=false
else
echo "," >> "$report_file"
fi
echo " \"$app\"" >> "$report_file"
done
cat >> "$report_file" << EOF
],
"system_info": {
"os_version": "$(sw_vers -productVersion)",
"build_version": "$(sw_vers -buildVersion)",
"serial_number": "$(system_profiler SPHardwareDataType | grep 'Serial Number' | awk '{print $4}')"
}
}
EOF
log_action "✅ Rapport de déploiement généré : $report_file"
echo "$report_file"
}
# Lister tous les LaunchAgents configurés
list_configured_apps() {
log_action "Liste des applications de lancement automatique configurées"
echo "=== LaunchAgents Gérés par MacFleet ==="
local agent_count=0
for plist_file in "$LAUNCH_AGENTS_DIR"/com.macfleet.*.plist; do
if [[ -f "$plist_file" ]]; then
local label
local program
label=$(defaults read "$plist_file" Label 2>/dev/null || echo "Inconnu")
program=$(defaults read "$plist_file" Program 2>/dev/null || echo "Inconnu")
echo "Étiquette : $label"
echo "Programme : $program"
echo "Fichier : $plist_file"
echo "---"
agent_count=$((agent_count + 1))
fi
done
echo "Total des LaunchAgents gérés : $agent_count"
}
# Valider toutes les applications configurées
validate_all_apps() {
log_action "Validation de toutes les applications configurées"
local validation_report="$CONFIG_DIR/validation_report_$(date '+%Y%m%d_%H%M%S').json"
local valid_count=0
local invalid_count=0
local invalid_apps=()
cat > "$validation_report" << EOF
{
"validation_timestamp": "$(date -Iseconds)",
"hostname": "$(hostname)",
"validation_results": [
EOF
local first=true
for plist_file in "$LAUNCH_AGENTS_DIR"/com.macfleet.*.plist; do
if [[ -f "$plist_file" ]]; then
if [[ "$first" == true ]]; then
first=false
else
echo "," >> "$validation_report"
fi
local label
local program
local exists="false"
local executable="false"
label=$(defaults read "$plist_file" Label 2>/dev/null || echo "Inconnu")
program=$(defaults read "$plist_file" Program 2>/dev/null || echo "Inconnu")
if [[ -f "$program" ]]; then
exists="true"
if [[ -x "$program" ]]; then
executable="true"
valid_count=$((valid_count + 1))
else
invalid_count=$((invalid_count + 1))
invalid_apps+=("$label")
fi
else
invalid_count=$((invalid_count + 1))
invalid_apps+=("$label")
fi
cat >> "$validation_report" << EOF
{
"label": "$label",
"program": "$program",
"file_exists": $exists,
"executable": $executable,
"valid": $([ "$exists" = "true" ] && [ "$executable" = "true" ] && echo "true" || echo "false")
}
EOF
fi
done
cat >> "$validation_report" << EOF
],
"validation_summary": {
"total_agents": $((valid_count + invalid_count)),
"valid_agents": $valid_count,
"invalid_agents": $invalid_count
}
}
EOF
log_action "✅ Validation terminée : $valid_count valides, $invalid_count invalides"
log_action "Rapport de validation : $validation_report"
if [[ $invalid_count -gt 0 ]]; then
log_action "Applications invalides trouvées : ${invalid_apps[*]}"
fi
echo "$validation_report"
}
# Nettoyer les LaunchAgents invalides ou orphelins
cleanup_launch_agents() {
log_action "Nettoyage des LaunchAgents invalides"
local cleanup_count=0
local cleanup_report="$CONFIG_DIR/cleanup_report_$(date '+%Y%m%d_%H%M%S').txt"
echo "Rapport de Nettoyage LaunchAgent MacFleet" > "$cleanup_report"
echo "Généré : $(date)" >> "$cleanup_report"
echo "======================================" >> "$cleanup_report"
for plist_file in "$LAUNCH_AGENTS_DIR"/com.macfleet.*.plist; do
if [[ -f "$plist_file" ]]; then
local program
program=$(defaults read "$plist_file" Program 2>/dev/null || echo "")
if [[ -n "$program" ]] && [[ ! -x "$program" ]]; then
local label
label=$(defaults read "$plist_file" Label 2>/dev/null || echo "Inconnu")
log_action "Suppression du LaunchAgent invalide : $label"
echo "Supprimé : $label ($program non trouvé/exécutable)" >> "$cleanup_report"
# Décharger si chargé
launchctl unload "$plist_file" 2>/dev/null || true
# Supprimer le fichier
rm -f "$plist_file"
cleanup_count=$((cleanup_count + 1))
fi
fi
done
echo "Total nettoyé : $cleanup_count" >> "$cleanup_report"
log_action "✅ Nettoyage terminé : $cleanup_count agents supprimés"
echo "$cleanup_report"
}
# Tester le lancement d'application
test_app_launch() {
local app_name="$1"
local plist_name="com.macfleet.${app_name// /_}.plist"
local plist_path="$LAUNCH_AGENTS_DIR/$plist_name"
if [[ ! -f "$plist_path" ]]; then
log_action "❌ LaunchAgent non trouvé : $plist_name"
return 1
fi
log_action "Test du lancement d'application : $app_name"
# Charger le LaunchAgent
if launchctl load "$plist_path" 2>/dev/null; then
log_action "✅ LaunchAgent chargé avec succès"
# Attendre un moment et vérifier si le processus fonctionne
sleep 2
if pgrep -f "$app_name" >/dev/null; then
log_action "✅ L'application fonctionne : $app_name"
return 0
else
log_action "⚠️ L'application n'a peut-être pas démarré correctement"
return 1
fi
else
log_action "❌ Échec du chargement du LaunchAgent"
return 1
fi
}
# Fonction d'exécution principale
main() {
local action="${1:-list}"
local profile_name="$2"
local username="$3"
log_action "=== Démarrage de la Gestion de Lancement d'Applications MacFleet ==="
log_action "Action : $action"
log_action "Profil : ${profile_name:-N/A}"
log_action "Utilisateur : ${username:-$(whoami)}"
# Configuration
setup_directories
case "$action" in
"deploy")
if [[ -z "$profile_name" ]]; then
echo "Profils disponibles :"
for profile in "${!USER_PROFILES[@]}"; do
echo " - $profile : ${USER_PROFILES[$profile]}"
done
echo ""
echo "Usage : $0 deploy <nom_profil> [nom_utilisateur]"
exit 1
fi
deploy_user_profile "$profile_name" "$username"
;;
"list")
list_configured_apps
;;
"validate")
validate_all_apps
;;
"cleanup")
cleanup_launch_agents
;;
"test")
if [[ -z "$profile_name" ]]; then
echo "Usage : $0 test <nom_app>"
exit 1
fi
test_app_launch "$profile_name"
;;
"remove")
if [[ -z "$profile_name" ]]; then
echo "Usage : $0 remove <nom_app>"
exit 1
fi
remove_launch_agent "$profile_name"
;;
"backup")
backup_launch_agents
;;
*)
echo "Usage : $0 {deploy|list|validate|cleanup|test|remove|backup}"
echo " deploy - Déployer les applications de profil utilisateur"
echo " list - Lister les LaunchAgents configurés"
echo " validate - Valider toutes les applications configurées"
echo " cleanup - Supprimer les LaunchAgents invalides"
echo " test - Tester le lancement d'application spécifique"
echo " remove - Supprimer un LaunchAgent spécifique"
echo " backup - Sauvegarder les LaunchAgents actuels"
exit 1
;;
esac
log_action "=== Gestion de lancement d'applications terminée ==="
}
# Exécuter la fonction principale
main "$@"
Configuration LaunchAgent Avancée
Lancement d'Application Conditionnel
#!/bin/bash
# Créer un LaunchAgent conditionnel basé sur l'état du système
create_conditional_launch_agent() {
local app_name="$1"
local app_path="$2"
local condition="$3" # network, power, time
local plist_name="com.macfleet.conditional.${app_name// /_}.plist"
cat > "/Library/LaunchAgents/${plist_name}" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${plist_name}</string>
<key>Program</key>
<string>${app_path}/Contents/MacOS/${app_name}</string>
<key>RunAtLoad</key>
<true/>
EOF
case "$condition" in
"network")
cat >> "/Library/LaunchAgents/${plist_name}" << EOF
<key>KeepAlive</key>
<dict>
<key>NetworkState</key>
<true/>
</dict>
EOF
;;
"power")
cat >> "/Library/LaunchAgents/${plist_name}" << EOF
<key>KeepAlive</key>
<dict>
<key>PowerManagement</key>
<true/>
</dict>
EOF
;;
"time")
cat >> "/Library/LaunchAgents/${plist_name}" << EOF
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>9</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
EOF
;;
esac
cat >> "/Library/LaunchAgents/${plist_name}" << EOF
</dict>
</plist>
EOF
echo "LaunchAgent conditionnel créé : $plist_name"
}
Lancement d'Application Conscient des Ressources
#!/bin/bash
# Créer un LaunchAgent conscient des ressources avec limitation
create_resource_aware_agent() {
local app_name="$1"
local app_path="$2"
local cpu_limit="$3" # pourcentage
local memory_limit="$4" # MB
local plist_name="com.macfleet.resource.${app_name// /_}.plist"
cat > "/Library/LaunchAgents/${plist_name}" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>${plist_name}</string>
<key>Program</key>
<string>${app_path}/Contents/MacOS/${app_name}</string>
<key>RunAtLoad</key>
<true/>
<key>ThrottleInterval</key>
<integer>60</integer>
<key>SoftResourceLimits</key>
<dict>
<key>CPU</key>
<integer>$cpu_limit</integer>
<key>Mem</key>
<integer>$((memory_limit * 1024 * 1024))</integer>
</dict>
<key>HardResourceLimits</key>
<dict>
<key>CPU</key>
<integer>$((cpu_limit + 10))</integer>
<key>Mem</key>
<integer>$((memory_limit * 1024 * 1024 * 2))</integer>
</dict>
</dict>
</plist>
EOF
echo "LaunchAgent conscient des ressources créé : $plist_name"
}
Gestion de Profils Utilisateur
Attribution Dynamique de Profil
#!/bin/bash
# Attribuer un profil basé sur les attributs utilisateur
assign_user_profile() {
local username="$1"
# Obtenir les informations utilisateur
local user_groups
user_groups=$(groups "$username" 2>/dev/null)
# Déterminer le profil basé sur l'appartenance au groupe
if [[ "$user_groups" =~ developer|engineering ]]; then
echo "developpeur"
elif [[ "$user_groups" =~ design|creative ]]; then
echo "designer"
elif [[ "$user_groups" =~ manager|executive ]]; then
echo "manager"
elif [[ "$user_groups" =~ security|admin ]]; then
echo "securite"
else
echo "defaut"
fi
}
# Auto-configurer l'utilisateur à la première connexion
auto_configure_user() {
local username="$(whoami)"
local assigned_profile
assigned_profile=$(assign_user_profile "$username")
echo "Auto-configuration de l'utilisateur : $username"
echo "Profil attribué : $assigned_profile"
# Déployer le profil
deploy_user_profile "$assigned_profile" "$username"
}
Modèles de Profil
#!/bin/bash
# Créer un modèle de profil personnalisé
create_profile_template() {
local template_name="$1"
local template_file="$CONFIG_DIR/profiles/${template_name}.json"
mkdir -p "$(dirname "$template_file")"
cat > "$template_file" << EOF
{
"profile_name": "$template_name",
"description": "Modèle de profil personnalisé",
"applications": [
{
"name": "Nom de l'Application",
"path": "/Applications/App.app",
"required": true,
"delay": 0,
"conditions": []
}
],
"settings": {
"auto_update": true,
"notifications": true,
"logging": true
}
}
EOF
echo "Modèle de profil créé : $template_file"
}
Sécurité et Validation
Vérification de Sécurité d'Application
#!/bin/bash
# Vérifier la sécurité de l'application avant le lancement
verify_app_security() {
local app_path="$1"
echo "=== Vérification de Sécurité d'Application ==="
# Vérifier la signature de code
if codesign -v "$app_path" 2>/dev/null; then
echo "✅ Signature de code valide"
else
echo "❌ Signature de code invalide ou manquante"
return 1
fi
# Vérifier la notarisation
if spctl -a -v "$app_path" 2>/dev/null | grep -q "accepted"; then
echo "✅ Application notarisée"
else
echo "⚠️ Application non notarisée"
fi
# Vérifier les attributs de quarantaine
if xattr -l "$app_path" | grep -q "com.apple.quarantine"; then
echo "⚠️ L'application a des attributs de quarantaine"
else
echo "✅ Pas d'attributs de quarantaine"
fi
# Vérifier les caractéristiques suspectes
local info_plist="${app_path}/Contents/Info.plist"
if [[ -f "$info_plist" ]]; then
local bundle_id
bundle_id=$(defaults read "$info_plist" CFBundleIdentifier 2>/dev/null)
echo "Bundle ID : $bundle_id"
# Vérifier les identifiants de bundle suspects
if [[ "$bundle_id" =~ (malware|hack|crack) ]]; then
echo "❌ Identifiant de bundle suspect détecté"
return 1
fi
fi
echo "✅ Vérification de sécurité terminée"
return 0
}
Vérifications de Conformité d'Entreprise
#!/bin/bash
# Vérifier les exigences de conformité d'entreprise
check_enterprise_compliance() {
local app_path="$1"
echo "=== Vérification de Conformité d'Entreprise ==="
# Vérifier si l'application est dans la liste approuvée
local approved_apps_file="/etc/macfleet/approved_apps.txt"
if [[ -f "$approved_apps_file" ]]; then
local app_name
app_name=$(basename "$app_path" .app)
if grep -q "^$app_name$" "$approved_apps_file"; then
echo "✅ L'application est dans la liste approuvée"
else
echo "❌ L'application n'est pas dans la liste approuvée"
return 1
fi
fi
# Vérifier les certificats d'entreprise
local cert_info
cert_info=$(codesign -dv "$app_path" 2>&1)
if echo "$cert_info" | grep -q "Developer ID\|Mac App Store"; then
echo "✅ Certificat développeur valide"
else
echo "⚠️ Pas de certificat développeur valide"
fi
return 0
}
Surveillance et Maintenance
Surveillance du Succès de Lancement
#!/bin/bash
# Surveiller le succès de lancement d'applications
monitor_launch_success() {
local monitoring_log="/var/log/macfleet_launch_monitoring.log"
echo "=== Surveillance du Succès de Lancement ===" | tee -a "$monitoring_log"
echo "Horodatage : $(date)" | tee -a "$monitoring_log"
# Vérifier chaque LaunchAgent configuré
for plist_file in "$LAUNCH_AGENTS_DIR"/com.macfleet.*.plist; do
if [[ -f "$plist_file" ]]; then
local label
local program
label=$(defaults read "$plist_file" Label 2>/dev/null)
program=$(defaults read "$plist_file" Program 2>/dev/null)
# Vérifier si l'application fonctionne
local app_name
app_name=$(basename "$program")
if pgrep -f "$app_name" >/dev/null; then
echo "✅ $label : En cours d'exécution" | tee -a "$monitoring_log"
else
echo "❌ $label : Pas en cours d'exécution" | tee -a "$monitoring_log"
# Essayer de redémarrer
launchctl unload "$plist_file" 2>/dev/null
launchctl load "$plist_file" 2>/dev/null
echo "🔄 Tentative de redémarrage pour $label" | tee -a "$monitoring_log"
fi
fi
done
}
Maintenance Automatisée
#!/bin/bash
# Configurer la planification de maintenance automatisée
setup_maintenance_schedule() {
local maintenance_script="/usr/local/bin/macfleet_app_maintenance.sh"
local launchd_plist="/Library/LaunchDaemons/com.macfleet.app.maintenance.plist"
# Créer le script de maintenance
cat > "$maintenance_script" << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/macfleet_app_maintenance.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "$(date): Démarrage de la maintenance d'applications"
# Valider toutes les applications
/usr/local/bin/macfleet_app_manager.sh validate
# Surveiller le succès de lancement
monitor_launch_success
# Nettoyer les agents invalides
/usr/local/bin/macfleet_app_manager.sh cleanup
echo "$(date): Maintenance d'applications terminée"
EOF
chmod +x "$maintenance_script"
# Créer le LaunchDaemon pour la maintenance programmée
cat > "$launchd_plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.macfleet.app.maintenance</string>
<key>ProgramArguments</key>
<array>
<string>$maintenance_script</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>2</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>RunAtLoad</key>
<false/>
</dict>
</plist>
EOF
# Charger le LaunchDaemon
sudo launchctl load "$launchd_plist"
echo "Maintenance automatisée configurée"
echo "Script : $maintenance_script"
echo "Planification : Quotidien à 2h00"
}
Meilleures Pratiques
🚀 Optimisation des Performances
- Échelonnez les lancements d'applications pour éviter la contention de ressources
- Utilisez des limites de ressources pour éviter la surcharge du système
- Surveillez le succès de lancement et implémentez le redémarrage automatique
- Validez les applications avant le déploiement
🔐 Directives de Sécurité
- Vérifiez les signatures de code avant d'autoriser le lancement automatique
- Maintenez des listes d'applications approuvées pour la conformité d'entreprise
- Utilisez des chemins sécurisés et évitez les emplacements accessibles en écriture par l'utilisateur
- Audits de sécurité réguliers des applications configurées
📋 Meilleures Pratiques de Gestion
- Déploiement basé sur les profils pour différents types d'utilisateurs
- Gestion de configuration centralisée
- Sauvegarde régulière des configurations LaunchAgent
- Surveillance et maintenance automatisées
🔍 Conseils de Dépannage
- Vérifiez les chemins d'applications et les exécutables
- Vérifiez la syntaxe LaunchAgent en utilisant plutil
- Surveillez les journaux système pour les erreurs de lancement
- Testez les configurations avant le déploiement de flotte
Notes Importantes
- Les LaunchAgents fonctionnent par utilisateur tandis que les LaunchDaemons fonctionnent à l'échelle du système
- Les applications doivent être correctement signées pour le déploiement d'entreprise
- Les limites de ressources aident à prévenir les problèmes de performance du système
- La validation régulière assure le fonctionnement continu
- Sauvegardez les configurations avant de faire des changements