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.

Manage FileVault Encryption on macOS

FileVault provides full-disk encryption for macOS devices, protecting sensitive data even if the device is lost or stolen. This tutorial shows how to automate FileVault management across your MacFleet using command-line scripts.

Understanding FileVault

FileVault encrypts the entire startup disk using XTS-AES-128 encryption with a 256-bit key. Key benefits include:

  • Data Protection - Encrypts all data on the startup disk
  • Compliance - Meets enterprise security requirements
  • Performance - Hardware-accelerated encryption on modern Macs
  • Recovery - Multiple recovery options available

Basic FileVault Commands

Check FileVault Status

#!/bin/bash

# Check current FileVault status
fdesetup status

# Get detailed encryption information
diskutil apfs listCryptoUsers /

Enable FileVault

#!/bin/bash

# Basic FileVault enable command
sudo fdesetup enable --user "username" --password "password"

# Enable with specific keychain
sudo fdesetup enable --user "username" --password "password" --keychain /Library/Keychains/System.keychain

Disable FileVault

#!/bin/bash

# Basic FileVault disable command
sudo fdesetup disable --user "username" --password "password"

Enterprise FileVault Management Script

Complete script for managing FileVault across your MacFleet:

#!/bin/bash

# FileVault Management Script for MacFleet
# Compatible with macOS 10.14+

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

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

# Function to get current user
get_current_user() {
    stat -f "%Su" /dev/console
}

# Function to check if user has secure token
check_secure_token() {
    local username="$1"
    
    if sysadminctl -secureTokenStatus "$username" 2>/dev/null | grep -q "ENABLED"; then
        return 0
    else
        return 1
    fi
}

# Function to check FileVault status
check_filevault_status() {
    local status
    status=$(fdesetup status)
    
    if echo "$status" | grep -q "FileVault is On"; then
        echo "enabled"
    elif echo "$status" | grep -q "FileVault is Off"; then
        echo "disabled"
    elif echo "$status" | grep -q "Encryption in progress"; then
        echo "encrypting"
    elif echo "$status" | grep -q "Decryption in progress"; then
        echo "decrypting"
    else
        echo "unknown"
    fi
}

# Function to get encryption progress
get_encryption_progress() {
    fdesetup status | grep -o '[0-9]\+%' | head -1
}

# Function to validate user credentials
validate_user_credentials() {
    local username="$1"
    local password="$2"
    
    # Check if user exists
    if ! id "$username" &>/dev/null; then
        log_message "✗ User does not exist: $username"
        return 1
    fi
    
    # Check if user has admin privileges
    if ! dsmemberutil checkmembership -U "$username" -G admin &>/dev/null; then
        log_message "✗ User is not an administrator: $username"
        return 1
    fi
    
    # Check if user has secure token
    if ! check_secure_token "$username"; then
        log_message "✗ User does not have secure token: $username"
        return 1
    fi
    
    # Verify password (basic check)
    if [[ -z "$password" ]]; then
        log_message "✗ Password cannot be empty for user: $username"
        return 1
    fi
    
    log_message "✓ User credentials validated: $username"
    return 0
}

# Function to enable FileVault
enable_filevault() {
    local username="$1"
    local password="$2"
    local force_enable="$3"
    
    log_message "Starting FileVault enablement for user: $username"
    
    # Check current status
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "enabled")
            log_message "! FileVault is already enabled"
            if [[ "$force_enable" != "true" ]]; then
                return 0
            fi
            ;;
        "encrypting")
            log_message "! FileVault encryption is already in progress"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Encryption progress: ${progress:-Unknown}"
            return 0
            ;;
        "decrypting")
            log_message "✗ Cannot enable FileVault while decryption is in progress"
            return 1
            ;;
    esac
    
    # Validate user credentials
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Enable FileVault
    log_message "Enabling FileVault..."
    
    if fdesetup enable -user "$username" -password "$password" -keychain "$KEYCHAIN_PATH" 2>/dev/null; then
        log_message "✓ FileVault enable command executed successfully"
        
        # Wait a moment and check status
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "enabled")
                log_message "✓ FileVault is now enabled"
                ;;
            "encrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ FileVault encryption started (${progress:-0%})"
                ;;
            *)
                log_message "! FileVault status unclear: $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Failed to enable FileVault"
        return 1
    fi
}

# Function to disable FileVault
disable_filevault() {
    local username="$1"
    local password="$2"
    local force_disable="$3"
    
    log_message "Starting FileVault disablement for user: $username"
    
    # Check current status
    local current_status
    current_status=$(check_filevault_status)
    
    case "$current_status" in
        "disabled")
            log_message "! FileVault is already disabled"
            if [[ "$force_disable" != "true" ]]; then
                return 0
            fi
            ;;
        "decrypting")
            log_message "! FileVault decryption is already in progress"
            local progress
            progress=$(get_encryption_progress)
            log_message "  Decryption progress: ${progress:-Unknown}"
            return 0
            ;;
        "encrypting")
            log_message "✗ Cannot disable FileVault while encryption is in progress"
            return 1
            ;;
    esac
    
    # Validate user credentials
    if ! validate_user_credentials "$username" "$password"; then
        return 1
    fi
    
    # Disable FileVault
    log_message "Disabling FileVault..."
    
    if fdesetup disable -user "$username" -password "$password" 2>/dev/null; then
        log_message "✓ FileVault disable command executed successfully"
        
        # Wait a moment and check status
        sleep 5
        local new_status
        new_status=$(check_filevault_status)
        
        case "$new_status" in
            "disabled")
                log_message "✓ FileVault is now disabled"
                ;;
            "decrypting")
                local progress
                progress=$(get_encryption_progress)
                log_message "✓ FileVault decryption started (${progress:-0%})"
                ;;
            *)
                log_message "! FileVault status unclear: $new_status"
                ;;
        esac
        
        return 0
    else
        log_message "✗ Failed to disable FileVault"
        return 1
    fi
}

# Function to get system information
get_system_info() {
    log_message "=== System Information ==="
    log_message "Hostname: $(hostname)"
    log_message "macOS Version: $(sw_vers -productVersion)"
    log_message "Current User: $(get_current_user)"
    log_message "FileVault Status: $(check_filevault_status)"
    
    # Get FileVault users
    local fv_users
    fv_users=$(fdesetup list 2>/dev/null)
    if [[ -n "$fv_users" ]]; then
        log_message "FileVault Enabled Users:"
        echo "$fv_users" | while read -r line; do
            log_message "  $line"
        done
    fi
}

# Function to display usage
usage() {
    echo "Usage: $0 {enable|disable|status} [options]"
    echo ""
    echo "Commands:"
    echo "  enable    Enable FileVault"
    echo "  disable   Disable FileVault"
    echo "  status    Check FileVault status"
    echo ""
    echo "Options:"
    echo "  -u, --user USERNAME      Specify username"
    echo "  -p, --password PASSWORD  Specify password"
    echo "  -f, --force             Force operation even if already in desired state"
    echo "  -h, --help              Show this help message"
    echo ""
    echo "Examples:"
    echo "  $0 enable -u admin -p password123"
    echo "  $0 disable -u admin -p password123 -f"
    echo "  $0 status"
}

# Main function
main() {
    local command="$1"
    local username=""
    local password=""
    local force="false"
    
    # Parse arguments
    shift
    while [[ $# -gt 0 ]]; do
        case $1 in
            -u|--user)
                username="$2"
                shift 2
                ;;
            -p|--password)
                password="$2"
                shift 2
                ;;
            -f|--force)
                force="true"
                shift
                ;;
            -h|--help)
                usage
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                usage
                exit 1
                ;;
        esac
    done
    
    # Execute command
    case "$command" in
        "enable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Error: Username and password required for enable command"
                usage
                exit 1
            fi
            
            log_message "=== Starting FileVault Enable Operation ==="
            get_system_info
            
            if enable_filevault "$username" "$password" "$force"; then
                log_message "=== FileVault Enable Operation Completed Successfully ==="
                exit 0
            else
                log_message "=== FileVault Enable Operation Failed ==="
                exit 1
            fi
            ;;
        "disable")
            if [[ -z "$username" ]] || [[ -z "$password" ]]; then
                echo "Error: Username and password required for disable command"
                usage
                exit 1
            fi
            
            log_message "=== Starting FileVault Disable Operation ==="
            get_system_info
            
            if disable_filevault "$username" "$password" "$force"; then
                log_message "=== FileVault Disable Operation Completed Successfully ==="
                exit 0
            else
                log_message "=== FileVault Disable Operation Failed ==="
                exit 1
            fi
            ;;
        "status")
            get_system_info
            exit 0
            ;;
        *)
            echo "Error: Invalid command: $command"
            usage
            exit 1
            ;;
    esac
}

# Execute main function
main "$@"

Quick FileVault Scripts

Simple Enable Script

#!/bin/bash

USERNAME="admin"
PASSWORD="your_password_here"

if fdesetup enable -user "$USERNAME" -password "$PASSWORD"; then
    echo "FileVault enabled successfully"
else
    echo "Failed to enable FileVault"
    exit 1
fi

Simple Status Check

#!/bin/bash

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

if echo "$STATUS" | grep -q "FileVault is On"; then
    echo "✓ FileVault is enabled"
    exit 0
elif echo "$STATUS" | grep -q "FileVault is Off"; then
    echo "✗ FileVault is disabled"
    exit 1
else
    echo "! FileVault status unclear"
    exit 2
fi

Recovery Key Management

Generate Personal Recovery Key

#!/bin/bash

# Enable FileVault with personal recovery key
sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -outputplist > /tmp/filevault_key.plist

# Extract recovery key
RECOVERY_KEY=$(grep -A1 "RecoveryKey" /tmp/filevault_key.plist | tail -1 | sed 's/.*<string>\(.*\)<\/string>.*/\1/')

echo "Recovery Key: $RECOVERY_KEY"

# Securely store recovery key
echo "$RECOVERY_KEY" | sudo tee /var/root/filevault_recovery_key.txt
sudo chmod 600 /var/root/filevault_recovery_key.txt

# Clean up
rm -f /tmp/filevault_key.plist

Enable Institutional Recovery Key

#!/bin/bash

# Create institutional recovery key
CERT_PATH="/path/to/institutional_certificate.cer"

if [[ -f "$CERT_PATH" ]]; then
    sudo fdesetup enable -user "$USERNAME" -password "$PASSWORD" -certificate "$CERT_PATH"
    echo "FileVault enabled with institutional recovery key"
else
    echo "Institutional certificate not found: $CERT_PATH"
    exit 1
fi

Troubleshooting Common Issues

Fix Secure Token Issues

#!/bin/bash

USERNAME="admin"

# Grant secure token to user
sudo sysadminctl -secureTokenOn "$USERNAME" -password -

# Verify secure token
if sysadminctl -secureTokenStatus "$USERNAME" | grep -q "ENABLED"; then
    echo "✓ Secure token enabled for $USERNAME"
else
    echo "✗ Failed to enable secure token for $USERNAME"
fi

Handle Blank Password Error

#!/bin/bash

USERNAME="admin"

# Check if user has a password set
if dscl . -read "/Users/$USERNAME" AuthenticationAuthority | grep -q "No such key"; then
    echo "User $USERNAME has no password set"
    echo "Setting password..."
    sudo dscl . -passwd "/Users/$USERNAME" "" "new_password_here"
fi

Monitoring and Reporting

FileVault Status Report

#!/bin/bash

# Generate FileVault status report
REPORT_FILE="/tmp/filevault_report.txt"

{
    echo "=== FileVault Status Report ==="
    echo "Generated: $(date)"
    echo "Hostname: $(hostname)"
    echo ""
    
    echo "=== FileVault Status ==="
    fdesetup status
    echo ""
    
    echo "=== Enabled Users ==="
    fdesetup list
    echo ""
    
    echo "=== Secure Token Status ==="
    for user in $(dscl . -list /Users | grep -v '^_'); do
        if [[ "$user" != "daemon" ]] && [[ "$user" != "nobody" ]]; then
            token_status=$(sysadminctl -secureTokenStatus "$user" 2>/dev/null | grep -o "ENABLED\|DISABLED")
            echo "User: $user - Token: ${token_status:-UNKNOWN}"
        fi
    done
    
} > "$REPORT_FILE"

echo "Report generated: $REPORT_FILE"

Common Error Solutions

ErrorCauseSolution
"Blank password"User has no passwordSet password with dscl . -passwd
"Master keychain found"Keychain ambiguityAdd -keychain parameter
"Secure token required"User lacks secure tokenGrant token with sysadminctl
"Already encrypted"FileVault already onUse -force or check status first
"Encryption in progress"Concurrent operationWait for completion

Security Best Practices

  • Use strong passwords for FileVault-enabled accounts
  • Store recovery keys securely in enterprise key management
  • Test scripts on isolated devices before fleet deployment
  • Monitor encryption progress to ensure completion
  • Backup recovery keys before making changes
  • Validate user permissions before attempting operations

Performance Considerations

  • Initial encryption can take several hours
  • System performance may be impacted during encryption
  • Schedule operations during maintenance windows
  • Monitor disk space (encryption requires free space)
  • Consider SSD vs HDD performance differences

Important Notes

  • FileVault requires admin privileges and secure tokens
  • Recovery keys are essential for data recovery
  • Encryption/decryption cannot be interrupted safely
  • Test all scripts thoroughly before production use
  • Always have a backup recovery plan

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.