Tutorial

Nuevas actualizaciones y mejoras para Macfleet.

Aviso importante

Los ejemplos de código y scripts proporcionados en estos tutoriales son solo para propósitos educativos. Macfleet no es responsable de ningún problema, daño o vulnerabilidad de seguridad que pueda surgir del uso, modificación o implementación de estos ejemplos. Siempre revisa y prueba el código en un entorno seguro antes de usarlo en sistemas de producción.

Get Versions of Installed Apps on macOS

Managing a Mac fleet requires keeping track of application versions across all devices. This tutorial shows you how to create and deploy scripts to retrieve application versions on macOS devices remotely.

Why Application Version Tracking Matters

Application version tracking is crucial for:

  • Security compliance: Ensuring all devices run supported software versions
  • License management: Tracking software deployments and compliance
  • Update planning: Identifying devices that need application updates
  • Support efficiency: Quickly identifying software versions during troubleshooting
  • Inventory management: Maintaining accurate software asset records

Basic Application Version Retrieval

Using mdls Command

The mdls command reads metadata attributes from files, including application version information stored in the kMDItemVersion attribute.

#!/bin/bash

# Basic script to get application versions
applications=("Safari" "Mail" "Calendar" "Notes" "Contacts")
heading_printed=false

for app in "${applications[@]}"; do
    version=$(mdls -name kMDItemVersion "/Applications/${app}.app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
    
    if [ -z "$version" ]; then
        echo "Unable to retrieve version for ${app}"
    else
        if [ "$heading_printed" = false ]; then
            echo "Application Versions:"
            heading_printed=true
        fi
        echo "${app}: ${version}"
    fi
done

Enhanced Version Script with User Context

For applications installed in user-specific locations, you may need to run the script with user context:

#!/bin/bash

# Enhanced script with user context support
applications=("Safari" "Mail" "Calendar" "Notes" "Contacts" "Xcode" "Final Cut Pro")
current_user=$(whoami)
heading_printed=false

echo "Checking application versions for user: $current_user"
echo "Date: $(date)"
echo "----------------------------------------"

for app in "${applications[@]}"; do
    # Try system Applications folder first
    version=$(mdls -name kMDItemVersion "/Applications/${app}.app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
    
    # If not found, try user Applications folder
    if [ -z "$version" ]; then
        version=$(mdls -name kMDItemVersion "/Users/$current_user/Applications/${app}.app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
    fi
    
    if [ -z "$version" ]; then
        echo "❌ Unable to retrieve version for ${app}"
    else
        if [ "$heading_printed" = false ]; then
            echo "Application Versions:"
            heading_printed=true
        fi
        echo "✅ ${app}: ${version}"
    fi
done

Advanced Application Inventory Scripts

Comprehensive Application Scanner

#!/bin/bash

# Comprehensive application version scanner
OUTPUT_FILE="/tmp/app_versions_$(date +%Y%m%d_%H%M%S).txt"
DEVICE_NAME=$(scutil --get ComputerName)
DEVICE_USER=$(whoami)

echo "MacFleet Application Version Report" > "$OUTPUT_FILE"
echo "=====================================" >> "$OUTPUT_FILE"
echo "Device: $DEVICE_NAME" >> "$OUTPUT_FILE"
echo "User: $DEVICE_USER" >> "$OUTPUT_FILE"
echo "Date: $(date)" >> "$OUTPUT_FILE"
echo "macOS Version: $(sw_vers -productVersion)" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"

# Function to get app version and additional info
get_app_info() {
    local app_path="$1"
    local app_name=$(basename "$app_path" .app)
    
    if [ -d "$app_path" ]; then
        local version=$(mdls -name kMDItemVersion "$app_path" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        local bundle_id=$(mdls -name kMDItemCFBundleIdentifier "$app_path" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        local size=$(du -sh "$app_path" 2>/dev/null | cut -f1)
        local modified=$(stat -f "%Sm" -t "%Y-%m-%d %H:%M:%S" "$app_path" 2>/dev/null)
        
        if [ -n "$version" ]; then
            echo "Application: $app_name" >> "$OUTPUT_FILE"
            echo "  Version: $version" >> "$OUTPUT_FILE"
            echo "  Bundle ID: $bundle_id" >> "$OUTPUT_FILE"
            echo "  Size: $size" >> "$OUTPUT_FILE"
            echo "  Modified: $modified" >> "$OUTPUT_FILE"
            echo "  Path: $app_path" >> "$OUTPUT_FILE"
            echo "" >> "$OUTPUT_FILE"
        fi
    fi
}

# Scan system Applications folder
echo "System Applications:" >> "$OUTPUT_FILE"
echo "-------------------" >> "$OUTPUT_FILE"
if [ -d "/Applications" ]; then
    for app in /Applications/*.app; do
        get_app_info "$app"
    done
fi

# Scan user Applications folder
echo "User Applications:" >> "$OUTPUT_FILE"
echo "-----------------" >> "$OUTPUT_FILE"
if [ -d "/Users/$DEVICE_USER/Applications" ]; then
    for app in "/Users/$DEVICE_USER/Applications"/*.app; do
        get_app_info "$app"
    done
fi

# Scan Utilities folder
echo "Utilities:" >> "$OUTPUT_FILE"
echo "---------" >> "$OUTPUT_FILE"
if [ -d "/Applications/Utilities" ]; then
    for app in "/Applications/Utilities"/*.app; do
        get_app_info "$app"
    done
fi

echo "Report generated: $OUTPUT_FILE"
echo "Total applications found: $(grep -c "Application:" "$OUTPUT_FILE")"

# Optional: Display the report
cat "$OUTPUT_FILE"

Specific Application Version Checker

#!/bin/bash

# Check specific applications commonly used in enterprise environments
declare -A enterprise_apps=(
    ["Microsoft Word"]="/Applications/Microsoft Word.app"
    ["Microsoft Excel"]="/Applications/Microsoft Excel.app"
    ["Microsoft PowerPoint"]="/Applications/Microsoft PowerPoint.app"
    ["Microsoft Outlook"]="/Applications/Microsoft Outlook.app"
    ["Adobe Photoshop 2024"]="/Applications/Adobe Photoshop 2024/Adobe Photoshop 2024.app"
    ["Adobe Illustrator 2024"]="/Applications/Adobe Illustrator 2024/Adobe Illustrator 2024.app"
    ["Slack"]="/Applications/Slack.app"
    ["Zoom"]="/Applications/zoom.us.app"
    ["Google Chrome"]="/Applications/Google Chrome.app"
    ["Firefox"]="/Applications/Firefox.app"
    ["Visual Studio Code"]="/Applications/Visual Studio Code.app"
    ["Docker Desktop"]="/Applications/Docker.app"
    ["Xcode"]="/Applications/Xcode.app"
)

echo "Application Version Check"
echo "==================================="
echo "Device: $(scutil --get ComputerName)"
echo "Date: $(date)"
echo ""

for app_name in "${!enterprise_apps[@]}"; do
    app_path="${enterprise_apps[$app_name]}"
    
    if [ -d "$app_path" ]; then
        version=$(mdls -name kMDItemVersion "$app_path" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        bundle_id=$(mdls -name kMDItemCFBundleIdentifier "$app_path" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        
        if [ -n "$version" ]; then
            echo "✅ $app_name: $version"
            echo "   Bundle ID: $bundle_id"
        else
            echo "⚠️  $app_name: Installed but version unavailable"
        fi
    else
        echo "❌ $app_name: Not installed"
    fi
done

# Check for critical security applications
echo ""
echo "Security Applications:"
echo "--------------------"
security_apps=("Antivirus One" "Malwarebytes" "CleanMyMac" "Little Snitch")

for app in "${security_apps[@]}"; do
    if [ -d "/Applications/${app}.app" ]; then
        version=$(mdls -name kMDItemVersion "/Applications/${app}.app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        echo "✅ $app: ${version:-Version unavailable}"
    else
        echo "❌ $app: Not installed"
    fi
done

Remote Deployment Scripts

Multi-Device Version Collection

#!/bin/bash

# Script for collecting application versions from multiple Mac devices
# This script should be deployed to each device and results collected centrally

CENTRAL_SERVER="your-macfleet-server.com"
DEVICE_ID=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk '{print $4}')
REPORT_FILE="/tmp/device_app_report_${DEVICE_ID}.json"

# Create JSON report
create_json_report() {
    local device_name=$(scutil --get ComputerName)
    local device_user=$(whoami)
    local os_version=$(sw_vers -productVersion)
    local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
    
    cat > "$REPORT_FILE" << EOF
{
  "device_info": {
    "device_id": "$DEVICE_ID",
    "device_name": "$device_name",
    "user": "$device_user",
    "os_version": "$os_version",
    "timestamp": "$timestamp"
  },
  "applications": [
EOF

    local first_app=true
    for app in /Applications/*.app; do
        if [ -d "$app" ]; then
            local app_name=$(basename "$app" .app)
            local version=$(mdls -name kMDItemVersion "$app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
            local bundle_id=$(mdls -name kMDItemCFBundleIdentifier "$app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
            
            if [ -n "$version" ]; then
                if [ "$first_app" = false ]; then
                    echo "," >> "$REPORT_FILE"
                fi
                
                cat >> "$REPORT_FILE" << EOF
    {
      "name": "$app_name",
      "version": "$version",
      "bundle_id": "$bundle_id",
      "path": "$app"
    }EOF
                first_app=false
            fi
        fi
    done
    
    echo "" >> "$REPORT_FILE"
    echo "  ]" >> "$REPORT_FILE"
    echo "}" >> "$REPORT_FILE"
}

# Create the report
create_json_report

# Display local results
echo "Application version report created: $REPORT_FILE"
echo "Device ID: $DEVICE_ID"
echo "Total applications: $(grep -c '"name":' "$REPORT_FILE")"

# Optional: Send to central server (uncomment if needed)
# curl -X POST -H "Content-Type: application/json" -d @"$REPORT_FILE" "https://$CENTRAL_SERVER/api/device-reports"

Automated Version Monitoring

#!/bin/bash

# Automated application version monitoring with alerting
ALERT_THRESHOLD_DAYS=30
LOG_FILE="/var/log/macfleet_app_monitor.log"
ALERT_FILE="/tmp/app_version_alerts.txt"

# Function to log messages
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Function to check if app needs update
check_app_age() {
    local app_path="$1"
    local app_name=$(basename "$app_path" .app)
    local modified_date=$(stat -f "%Sm" -t "%Y-%m-%d" "$app_path" 2>/dev/null)
    
    if [ -n "$modified_date" ]; then
        local days_old=$(( ($(date +%s) - $(date -j -f "%Y-%m-%d" "$modified_date" +%s)) / 86400 ))
        
        if [ $days_old -gt $ALERT_THRESHOLD_DAYS ]; then
            echo "⚠️  $app_name: Last modified $days_old days ago ($modified_date)" >> "$ALERT_FILE"
            log_message "ALERT: $app_name is $days_old days old"
        fi
    fi
}

# Initialize alert file
echo "MacFleet Application Age Alerts" > "$ALERT_FILE"
echo "================================" >> "$ALERT_FILE"
echo "Generated: $(date)" >> "$ALERT_FILE"
echo "Threshold: $ALERT_THRESHOLD_DAYS days" >> "$ALERT_FILE"
echo "" >> "$ALERT_FILE"

log_message "Starting application version monitoring"

# Check critical applications
critical_apps=("Safari" "Mail" "Calendar" "Microsoft Word" "Microsoft Excel" "Google Chrome" "Slack" "Zoom")

for app in "${critical_apps[@]}"; do
    if [ -d "/Applications/${app}.app" ]; then
        check_app_age "/Applications/${app}.app"
        
        version=$(mdls -name kMDItemVersion "/Applications/${app}.app" 2>/dev/null | grep -o '".*"' | sed 's/"//g')
        log_message "Checked $app: Version $version"
    else
        log_message "WARNING: $app not found"
    fi
done

# Display alerts if any
if [ -s "$ALERT_FILE" ] && [ $(wc -l < "$ALERT_FILE") -gt 4 ]; then
    echo "⚠️  Application age alerts found:"
    cat "$ALERT_FILE"
    
    # Optional: Send alerts via email or notification service
    # mail -s "MacFleet App Version Alerts - $(hostname)" admin@yourcompany.com < "$ALERT_FILE"
fi

log_message "Application version monitoring completed"

Best Practices for Mac Fleet Management

1. Regular Monitoring

  • Schedule version checks weekly or bi-weekly
  • Monitor critical business applications more frequently
  • Track both system and user-installed applications

2. Version Standardization

  • Maintain approved application version lists
  • Create policies for automatic updates
  • Document version compatibility requirements

3. Security Considerations

  • Prioritize security updates for all applications
  • Monitor for applications with known vulnerabilities
  • Implement approval workflows for major version updates

4. Reporting and Analytics

  • Generate regular compliance reports
  • Track update deployment success rates
  • Monitor application usage patterns

5. Automation Integration

  • Integrate with configuration management tools
  • Automate routine version checks
  • Set up alerts for version discrepancies

Troubleshooting Common Issues

Issue: mdls Command Not Found

# Verify command availability
which mdls
# If not found, check system integrity
sudo /usr/bin/mdutil -i on /

Issue: Permission Denied

# Run with appropriate permissions
sudo -u [username] mdls -name kMDItemVersion "/Applications/AppName.app"

Issue: Version Information Unavailable

# Try alternative methods
defaults read "/Applications/AppName.app/Contents/Info.plist" CFBundleShortVersionString
plutil -p "/Applications/AppName.app/Contents/Info.plist" | grep -i version

Issue: Applications in Non-Standard Locations

# Search for applications system-wide
find /Applications /Users/*/Applications -name "*.app" -type d 2>/dev/null

Conclusion

Application version tracking is essential for maintaining a secure and compliant Mac fleet. These scripts provide a foundation for:

  • Automated version discovery and reporting
  • Compliance monitoring and alerting
  • Security vulnerability assessment
  • Software asset management

Regular implementation of these monitoring practices will help ensure your Mac fleet remains secure, compliant, and properly managed.

For more advanced Mac fleet management capabilities, consider integrating these scripts with your existing configuration management and monitoring tools.

Tutorial

Nuevas actualizaciones y mejoras para Macfleet.

Configurando un Runner de GitHub Actions en un Mac Mini (Apple Silicon)

Runner de GitHub Actions

GitHub Actions es una plataforma poderosa de CI/CD que te permite automatizar tus flujos de trabajo de desarrollo de software. Aunque GitHub ofrece runners hospedados, los runners auto-hospedados proporcionan mayor control y personalización para tu configuración de CI/CD. Este tutorial te guía a través de la configuración y conexión de un runner auto-hospedado en un Mac mini para ejecutar pipelines de macOS.

Prerrequisitos

Antes de comenzar, asegúrate de tener:

  • Un Mac mini (regístrate en Macfleet)
  • Un repositorio de GitHub con derechos de administrador
  • Un gestor de paquetes instalado (preferiblemente Homebrew)
  • Git instalado en tu sistema

Paso 1: Crear una Cuenta de Usuario Dedicada

Primero, crea una cuenta de usuario dedicada para el runner de GitHub Actions:

# Crear la cuenta de usuario 'gh-runner'
sudo dscl . -create /Users/gh-runner
sudo dscl . -create /Users/gh-runner UserShell /bin/bash
sudo dscl . -create /Users/gh-runner RealName "GitHub runner"
sudo dscl . -create /Users/gh-runner UniqueID "1001"
sudo dscl . -create /Users/gh-runner PrimaryGroupID 20
sudo dscl . -create /Users/gh-runner NFSHomeDirectory /Users/gh-runner

# Establecer la contraseña para el usuario
sudo dscl . -passwd /Users/gh-runner tu_contraseña

# Agregar 'gh-runner' al grupo 'admin'
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Cambia a la nueva cuenta de usuario:

su gh-runner

Paso 2: Instalar Software Requerido

Instala Git y Rosetta 2 (si usas Apple Silicon):

# Instalar Git si no está ya instalado
brew install git

# Instalar Rosetta 2 para Macs Apple Silicon
softwareupdate --install-rosetta

Paso 3: Configurar el Runner de GitHub Actions

  1. Ve a tu repositorio de GitHub
  2. Navega a Configuración > Actions > Runners

Runner de GitHub Actions

  1. Haz clic en "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Selecciona macOS como imagen del runner y ARM64 como arquitectura
  3. Sigue los comandos proporcionados para descargar y configurar el runner

Runner de GitHub Actions

Crea un archivo .env en el directorio _work del runner:

# archivo _work/.env
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Ejecuta el script run.sh en tu directorio del runner para completar la configuración.
  2. Verifica que el runner esté activo y escuchando trabajos en la terminal y revisa la configuración del repositorio de GitHub para la asociación del runner y el estado Idle.

Runner de GitHub Actions

Paso 4: Configurar Sudoers (Opcional)

Si tus acciones requieren privilegios de root, configura el archivo sudoers:

sudo visudo

Agrega la siguiente línea:

gh-runner ALL=(ALL) NOPASSWD: ALL

Paso 5: Usar el Runner en Flujos de Trabajo

Configura tu flujo de trabajo de GitHub Actions para usar el runner auto-hospedado:

name: Flujo de trabajo de muestra

on:
  workflow_dispatch:

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

El runner está autenticado en tu repositorio y etiquetado con self-hosted, macOS, y ARM64. Úsalo en tus flujos de trabajo especificando estas etiquetas en el campo runs-on:

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

Mejores Prácticas

  • Mantén tu software del runner actualizado
  • Monitorea regularmente los logs del runner para problemas
  • Usa etiquetas específicas para diferentes tipos de runners
  • Implementa medidas de seguridad apropiadas
  • Considera usar múltiples runners para balanceo de carga

Solución de Problemas

Problemas comunes y soluciones:

  1. Runner no conectando:

    • Verifica conectividad de red
    • Verifica validez del token de GitHub
    • Asegúrate de permisos apropiados
  2. Fallas de construcción:

    • Verifica instalación de Xcode
    • Verifica dependencias requeridas
    • Revisa logs del flujo de trabajo
  3. Problemas de permisos:

    • Verifica permisos de usuario
    • Verifica configuración de sudoers
    • Revisa permisos del sistema de archivos

Conclusión

Ahora tienes un runner auto-hospedado de GitHub Actions configurado en tu Mac mini. Esta configuración te proporciona más control sobre tu entorno de CI/CD y te permite ejecutar flujos de trabajo específicos de macOS de manera eficiente.

Recuerda mantener regularmente tu runner y mantenerlo actualizado con los últimos parches de seguridad y versiones de software.

Aplicación Nativa

Aplicación nativa de Macfleet

Guía de Instalación de Macfleet

Macfleet es una solución poderosa de gestión de flota diseñada específicamente para entornos de Mac Mini alojados en la nube. Como proveedor de hosting en la nube de Mac Mini, puedes usar Macfleet para monitorear, gestionar y optimizar toda tu flota de instancias Mac virtualizadas.

Esta guía de instalación te llevará a través de la configuración del monitoreo de Macfleet en sistemas macOS, Windows y Linux para asegurar una supervisión integral de tu infraestructura en la nube.

🍎 macOS

  • Descarga el archivo .dmg para Mac aquí
  • Haz doble clic en el archivo .dmg descargado
  • Arrastra la aplicación Macfleet a la carpeta Aplicaciones
  • Expulsa el archivo .dmg
  • Abre Preferencias del Sistema > Seguridad y Privacidad
    • Pestaña Privacidad > Accesibilidad
    • Marca Macfleet para permitir el monitoreo
  • Inicia Macfleet desde Aplicaciones
  • El seguimiento comienza automáticamente

🪟 Windows

  • Descarga el archivo .exe para Windows aquí
  • Haz clic derecho en el archivo .exe > "Ejecutar como administrador"
  • Sigue el asistente de instalación
  • Acepta los términos y condiciones
  • Permite en Windows Defender si se solicita
  • Concede permisos de monitoreo de aplicaciones
  • Inicia Macfleet desde el Menú Inicio
  • La aplicación comienza el seguimiento automáticamente

🐧 Linux

  • Descarga el paquete .deb (Ubuntu/Debian) o .rpm (CentOS/RHEL) aquí
  • Instala usando tu gestor de paquetes
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Permite permisos de acceso X11 si se solicita
  • Agrega el usuario a los grupos apropiados si es necesario
  • Inicia Macfleet desde el menú de Aplicaciones
  • La aplicación comienza el seguimiento automáticamente

Nota: Después de la instalación en todos los sistemas, inicia sesión con tus credenciales de Macfleet para sincronizar datos con tu panel de control.