Tutorial

Novas atualizações e melhorias para a Macfleet.

Aviso importante

Os exemplos de código e scripts fornecidos nestes tutoriais são apenas para fins educacionais. A Macfleet não é responsável por quaisquer problemas, danos ou vulnerabilidades de segurança que possam surgir do uso, modificação ou implementação destes exemplos. Sempre revise e teste o código em um ambiente seguro antes de usá-lo em sistemas de produção.

Sharing User Management on macOS

Manage sharing-only user accounts across your MacFleet devices using advanced dscl commands. This tutorial covers user creation, security policies, bulk deployment, and enterprise user lifecycle management.

Understanding macOS User Management

macOS uses Directory Service command line utility (dscl) for user management:

  • dscl - Directory Service command line utility
  • Local Directory - /var/db/dslocal/nodes/Default
  • User Records - Stored in /Users/ path
  • Sharing-only Users - Limited access accounts for file sharing

Basic Sharing User Creation

Simple Sharing User

#!/bin/bash

# Create a basic sharing-only user account
USERNAME="SharingUser"
DISPLAY_NAME="Sharing Account"
PASSWORD="SecurePass123"
USER_ID="550"

# Create the user
sudo dscl . create /Users/"$USERNAME"

# Set display name
sudo dscl . create /Users/"$USERNAME" RealName "$DISPLAY_NAME"

# Set password
sudo dscl . passwd /Users/"$USERNAME" "$PASSWORD"

# Set unique ID
sudo dscl . create /Users/"$USERNAME" UniqueID "$USER_ID"

# Set group ID (staff group)
sudo dscl . create /Users/"$USERNAME" PrimaryGroupID 20

# Deny shell access
sudo dscl . create /Users/"$USERNAME" UserShell /usr/bin/false

# No home directory
sudo dscl . create /Users/"$USERNAME" NFSHomeDirectory /dev/null

echo "Sharing user '$USERNAME' created successfully"

Enhanced Sharing User with Options

#!/bin/bash

# Enhanced sharing user creation with additional options
create_sharing_user() {
    local username="$1"
    local display_name="$2"
    local password="$3"
    local hint="$4"
    local picture_path="$5"
    local user_id="$6"
    
    echo "Creating sharing user: $username"
    
    # Create user
    sudo dscl . create /Users/"$username"
    
    # Set display name
    sudo dscl . create /Users/"$username" RealName "$display_name"
    
    # Set password
    sudo dscl . passwd /Users/"$username" "$password"
    
    # Set password hint (optional)
    if [[ -n "$hint" ]]; then
        sudo dscl . create /Users/"$username" hint "$hint"
    fi
    
    # Set profile picture (optional)
    if [[ -n "$picture_path" && -f "$picture_path" ]]; then
        sudo dscl . create /Users/"$username" picture "$picture_path"
    fi
    
    # Set unique ID
    sudo dscl . create /Users/"$username" UniqueID "$user_id"
    
    # Set group ID
    sudo dscl . create /Users/"$username" PrimaryGroupID 20
    
    # Deny shell access
    sudo dscl . create /Users/"$username" UserShell /usr/bin/false
    
    # No home directory
    sudo dscl . create /Users/"$username" NFSHomeDirectory /dev/null
    
    echo "✅ Sharing user '$username' created successfully"
    return 0
}

# Usage examples
create_sharing_user "FileShare" "File Sharing Account" "FilePass123" "File access only" "" "551"
create_sharing_user "GuestAccess" "Guest User" "GuestPass456" "Temporary access" "/System/Library/User Pictures/Animals/Butterfly.tif" "552"

Enterprise User Categories

User Type Classifications

#!/bin/bash

# Enterprise user categories with specific configurations
declare -A USER_CATEGORIES=(
    ["sharing_standard"]="Standard file sharing access"
    ["sharing_secure"]="High-security sharing with restrictions"
    ["guest_temporary"]="Temporary guest access with expiration"
    ["service_account"]="Service accounts for applications"
    ["departmental_shared"]="Department-specific shared accounts"
    ["external_partner"]="External partner limited access"
    ["kiosk_public"]="Public kiosk access accounts"
)

# Security policies for each category
declare -A SECURITY_POLICIES=(
    ["sharing_standard"]="password_policy:standard,audit_level:basic,session_timeout:8h"
    ["sharing_secure"]="password_policy:strong,audit_level:comprehensive,session_timeout:2h,mfa_required:true"
    ["guest_temporary"]="password_policy:basic,audit_level:full,session_timeout:1h,auto_expire:24h"
    ["service_account"]="password_policy:service,audit_level:system,no_interactive:true"
    ["departmental_shared"]="password_policy:department,audit_level:department,group_restrictions:true"
    ["external_partner"]="password_policy:external,audit_level:full,network_restrictions:true"
    ["kiosk_public"]="password_policy:public,audit_level:minimal,session_timeout:30m,reset_on_logout:true"
)

# Access control definitions
declare -A ACCESS_CONTROLS=(
    ["sharing_standard"]="file_sharing:read_write,print_access:yes,network_access:local"
    ["sharing_secure"]="file_sharing:read_only,print_access:restricted,network_access:vpn_only"
    ["guest_temporary"]="file_sharing:guest_folder,print_access:no,network_access:guest_wifi"
    ["service_account"]="file_sharing:service_dirs,print_access:no,network_access:service_ports"
    ["departmental_shared"]="file_sharing:department_dirs,print_access:department,network_access:department_vlan"
    ["external_partner"]="file_sharing:partner_dirs,print_access:no,network_access:partner_dmz"
    ["kiosk_public"]="file_sharing:public_docs,print_access:public,network_access:public_wifi"
)

print_user_categories() {
    echo "=== Available User Categories ==="
    for category in "${!USER_CATEGORIES[@]}"; do
        echo "Category: $category"
        echo "  Description: ${USER_CATEGORIES[$category]}"
        echo "  Security: ${SECURITY_POLICIES[$category]}"
        echo "  Access: ${ACCESS_CONTROLS[$category]}"
        echo ""
    done
}

# Display available categories
print_user_categories

User Management Policies

Password Policy Engine

#!/bin/bash

# Password policy definitions for different user types
generate_password_policy() {
    local policy_type="$1"
    
    case "$policy_type" in
        "standard")
            echo "min_length:8,complexity:medium,expiry:90d,history:5"
            ;;
        "strong")
            echo "min_length:12,complexity:high,expiry:60d,history:10,special_chars:required"
            ;;
        "basic")
            echo "min_length:6,complexity:low,expiry:never,history:3"
            ;;
        "service")
            echo "min_length:16,complexity:high,expiry:180d,history:20,machine_generated:true"
            ;;
        "department")
            echo "min_length:10,complexity:medium,expiry:120d,history:8,department_prefix:required"
            ;;
        "external")
            echo "min_length:14,complexity:high,expiry:30d,history:15,external_validation:required"
            ;;
        "public")
            echo "min_length:4,complexity:none,expiry:daily,history:1,auto_reset:true"
            ;;
        *)
            echo "min_length:8,complexity:medium,expiry:90d,history:5"
            ;;
    esac
}

# Generate secure password based on policy
generate_secure_password() {
    local policy="$1"
    local length
    local complexity
    
    # Parse policy
    length=$(echo "$policy" | grep -o 'min_length:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexity:[a-z]*' | cut -d: -f2)
    
    case "$complexity" in
        "high")
            # High complexity: uppercase, lowercase, numbers, special characters
            openssl rand -base64 $((length * 2)) | tr -d "=+/" | cut -c1-"$length" | sed 's/./&@1A/4'
            ;;
        "medium")
            # Medium complexity: uppercase, lowercase, numbers
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
        "low")
            # Low complexity: alphanumeric
            openssl rand -hex "$((length/2))" | cut -c1-"$length"
            ;;
        *)
            # Default medium complexity
            openssl rand -base64 "$length" | tr -d "=+/" | cut -c1-"$length"
            ;;
    esac
}

# Validate password against policy
validate_password() {
    local password="$1"
    local policy="$2"
    local min_length complexity
    
    min_length=$(echo "$policy" | grep -o 'min_length:[0-9]*' | cut -d: -f2)
    complexity=$(echo "$policy" | grep -o 'complexity:[a-z]*' | cut -d: -f2)
    
    # Check length
    if [[ ${#password} -lt $min_length ]]; then
        echo "❌ Password too short (minimum $min_length characters)"
        return 1
    fi
    
    # Check complexity
    case "$complexity" in
        "high")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] && "$password" =~ [^A-Za-z0-9] ]]; then
                echo "❌ Password must contain uppercase, lowercase, numbers, and special characters"
                return 1
            fi
            ;;
        "medium")
            if ! [[ "$password" =~ [A-Z] && "$password" =~ [a-z] && "$password" =~ [0-9] ]]; then
                echo "❌ Password must contain uppercase, lowercase, and numbers"
                return 1
            fi
            ;;
    esac
    
    echo "✅ Password meets policy requirements"
    return 0
}

Enterprise User Deployment Profiles

Deployment Configuration Templates

#!/bin/bash

# Enterprise deployment profiles for different organizational needs
declare -A DEPLOYMENT_PROFILES=(
    ["corporate_standard"]="Standard corporate deployment with basic security"
    ["high_security_finance"]="High-security deployment for financial departments"
    ["guest_access_lobby"]="Guest access deployment for lobby/public areas"
    ["partner_collaboration"]="External partner collaboration deployment"
    ["kiosk_public_library"]="Public kiosk deployment for libraries/public spaces"
    ["research_development"]="Research and development team deployment"
    ["executive_secure"]="Executive-level secure deployment"
)

# Profile-specific configurations
get_deployment_config() {
    local profile="$1"
    
    case "$profile" in
        "corporate_standard")
            cat << EOF
{
    "user_category": "sharing_standard",
    "password_policy": "standard",
    "access_level": "department_files",
    "session_timeout": "8h",
    "audit_level": "basic",
    "group_membership": ["staff", "file_sharing"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false
    },
    "monitoring": {
        "login_tracking": true,
        "file_access_log": true,
        "failed_attempts": 5
    }
}
EOF
            ;;
        "high_security_finance")
            cat << EOF
{
    "user_category": "sharing_secure",
    "password_policy": "strong",
    "access_level": "finance_restricted",
    "session_timeout": "2h",
    "audit_level": "comprehensive",
    "group_membership": ["finance", "secure_sharing"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false,
        "network_access": "finance_vlan_only",
        "time_restrictions": "business_hours"
    },
    "security": {
        "mfa_required": true,
        "encryption": "aes256",
        "key_rotation": "monthly"
    },
    "monitoring": {
        "real_time_alerts": true,
        "login_tracking": true,
        "file_access_log": true,
        "failed_attempts": 3,
        "compliance_reporting": "sox_hipaa"
    }
}
EOF
            ;;
        "guest_access_lobby")
            cat << EOF
{
    "user_category": "guest_temporary",
    "password_policy": "basic",
    "access_level": "guest_resources",
    "session_timeout": "1h",
    "audit_level": "full",
    "group_membership": ["guest", "public_access"],
    "restrictions": {
        "shell_access": false,
        "home_directory": false,
        "admin_privileges": false,
        "internet_access": "guest_wifi_only",
        "file_upload": false
    },
    "automation": {
        "auto_expire": "24h",
        "auto_cleanup": true,
        "reset_on_logout": true
    },
    "monitoring": {
        "session_recording": true,
        "login_tracking": true,
        "activity_log": true,
        "failed_attempts": 3
    }
}
EOF
            ;;
        *)
            echo "Unknown deployment profile: $profile"
            return 1
            ;;
    esac
}

# Apply deployment profile
apply_deployment_profile() {
    local profile="$1"
    local config_file="/tmp/deployment_config.json"
    
    echo "Applying deployment profile: $profile"
    
    # Get configuration
    get_deployment_config "$profile" > "$config_file"
    
    if [[ ! -f "$config_file" ]]; then
        echo "❌ Failed to generate configuration for profile: $profile"
        return 1
    fi
    
    echo "✅ Deployment configuration ready"
    echo "Configuration saved to: $config_file"
    
    # Parse and display key settings
    echo "=== Profile Summary ==="
    echo "User Category: $(jq -r '.user_category' "$config_file")"
    echo "Password Policy: $(jq -r '.password_policy' "$config_file")"
    echo "Access Level: $(jq -r '.access_level' "$config_file")"
    echo "Session Timeout: $(jq -r '.session_timeout' "$config_file")"
    echo "Audit Level: $(jq -r '.audit_level' "$config_file")"
    
    return 0
}

Enterprise User Management System

#!/bin/bash

# MacFleet Enterprise User Management System
# Comprehensive sharing user creation and management

# Configuration
CONFIG_DIR="/etc/macfleet/users"
LOG_FILE="/var/log/macfleet_user_management.log"
BACKUP_DIR="/var/backups/macfleet/users"
REPORTS_DIR="/var/reports/macfleet/users"
AUDIT_LOG="/var/log/macfleet_user_audit.log"

# Create required directories
create_directories() {
    local directories=("$CONFIG_DIR" "$BACKUP_DIR" "$REPORTS_DIR")
    
    for dir in "${directories[@]}"; do
        if [[ ! -d "$dir" ]]; then
            sudo mkdir -p "$dir"
            sudo chmod 755 "$dir"
        fi
    done
}

# Logging functions
log_action() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') [INFO] $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') [ERROR] $1" | tee -a "$LOG_FILE" >&2
}

audit_log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') [AUDIT] $1" | tee -a "$AUDIT_LOG"
}

# User ID management
get_next_user_id() {
    local start_id="$1"
    local current_id="$start_id"
    
    while dscl . list /Users UniqueID | awk '{print $2}' | grep -q "^${current_id}$"; do
        ((current_id++))
    done
    
    echo "$current_id"
}

# Comprehensive user creation function
create_enterprise_user() {
    local username="$1"
    local display_name="$2"
    local user_category="$3"
    local deployment_profile="$4"
    local department="$5"
    local expiry_date="$6"
    
    log_action "Starting user creation: $username (Category: $user_category, Profile: $deployment_profile)"
    
    # Validate inputs
    if [[ -z "$username" || -z "$display_name" || -z "$user_category" ]]; then
        log_error "Missing required parameters for user creation"
        return 1
    fi
    
    # Check if user already exists
    if dscl . read /Users/"$username" &>/dev/null; then
        log_error "User $username already exists"
        return 1
    fi
    
    # Get deployment configuration
    local config_file="/tmp/user_config_${username}.json"
    get_deployment_config "$deployment_profile" > "$config_file"
    
    # Parse configuration
    local password_policy
    password_policy=$(jq -r '.password_policy' "$config_file")
    
    # Get next available user ID
    local user_id
    user_id=$(get_next_user_id 550)
    
    # Generate secure password
    local policy_details
    policy_details=$(generate_password_policy "$password_policy")
    local password
    password=$(generate_secure_password "$policy_details")
    
    # Create user metadata
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    cat > "$metadata_file" << EOF
{
    "username": "$username",
    "display_name": "$display_name",
    "user_category": "$user_category",
    "deployment_profile": "$deployment_profile",
    "department": "$department",
    "user_id": $user_id,
    "created_date": "$(date -Iseconds)",
    "created_by": "$(whoami)",
    "expiry_date": "$expiry_date",
    "password_policy": "$password_policy",
    "status": "active"
}
EOF
    
    # Create the user
    log_action "Creating user record for $username"
    sudo dscl . create /Users/"$username" || {
        log_error "Failed to create user record for $username"
        return 1
    }
    
    # Set basic properties
    sudo dscl . create /Users/"$username" RealName "$display_name"
    sudo dscl . passwd /Users/"$username" "$password"
    sudo dscl . create /Users/"$username" UniqueID "$user_id"
    sudo dscl . create /Users/"$username" PrimaryGroupID 20
    sudo dscl . create /Users/"$username" UserShell /usr/bin/false
    sudo dscl . create /Users/"$username" NFSHomeDirectory /dev/null
    
    # Add custom attributes
    sudo dscl . create /Users/"$username" Comment "MacFleet managed user - $user_category"
    sudo dscl . create /Users/"$username" Keywords "macfleet,$user_category,$deployment_profile,$department"
    
    # Set expiry date if provided
    if [[ -n "$expiry_date" ]]; then
        sudo dscl . create /Users/"$username" ExpiryDate "$expiry_date"
    fi
    
    # Apply group memberships
    local groups
    groups=$(jq -r '.group_membership[]' "$config_file" 2>/dev/null)
    while IFS= read -r group; do
        if [[ -n "$group" && "$group" != "null" ]]; then
            sudo dseditgroup -o edit -a "$username" -t user "$group" 2>/dev/null || {
                log_action "Group $group does not exist, skipping"
            }
        fi
    done <<< "$groups"
    
    # Store secure password (encrypted)
    echo "$password" | openssl enc -aes-256-cbc -pbkdf2 -k "macfleet_$(hostname)" -out "$CONFIG_DIR/${username}_password.enc"
    
    # Create backup
    create_user_backup "$username"
    
    # Audit logging
    audit_log "User created: $username (UID: $user_id, Category: $user_category, Profile: $deployment_profile)"
    
    log_action "✅ User $username created successfully (UID: $user_id)"
    
    # Return password for initial communication (in production, use secure delivery)
    echo "CREATED_USER_INFO:$username:$password:$user_id"
    
    return 0
}

# Bulk user creation
bulk_create_users() {
    local csv_file="$1"
    local created_count=0
    local failed_count=0
    
    if [[ ! -f "$csv_file" ]]; then
        log_error "CSV file not found: $csv_file"
        return 1
    fi
    
    log_action "Starting bulk user creation from: $csv_file"
    
    # Process CSV file (skip header)
    tail -n +2 "$csv_file" | while IFS=',' read -r username display_name category profile department expiry; do
        if create_enterprise_user "$username" "$display_name" "$category" "$profile" "$department" "$expiry"; then
            ((created_count++))
        else
            ((failed_count++))
        fi
    done
    
    log_action "Bulk creation completed. Created: $created_count, Failed: $failed_count"
    
    # Generate report
    generate_user_report "bulk_creation_$(date +%Y%m%d_%H%M%S)"
}

# User management functions
list_enterprise_users() {
    echo "=== MacFleet Managed Users ==="
    echo "Username | Display Name | Category | Status | Created"
    echo "---------|--------------|----------|--------|--------"
    
    for metadata_file in "$CONFIG_DIR"/*_metadata.json; do
        if [[ -f "$metadata_file" ]]; then
            local username display_name category status created_date
            username=$(jq -r '.username' "$metadata_file")
            display_name=$(jq -r '.display_name' "$metadata_file")
            category=$(jq -r '.user_category' "$metadata_file")
            status=$(jq -r '.status' "$metadata_file")
            created_date=$(jq -r '.created_date' "$metadata_file" | cut -d'T' -f1)
            
            printf "%-8s | %-12s | %-8s | %-6s | %s\n" "$username" "$display_name" "$category" "$status" "$created_date"
        fi
    done
}

# User removal with cleanup
remove_enterprise_user() {
    local username="$1"
    local backup_before_removal="$2"
    
    log_action "Starting removal of user: $username"
    
    # Check if user exists
    if ! dscl . read /Users/"$username" &>/dev/null; then
        log_error "User $username does not exist"
        return 1
    fi
    
    # Create backup before removal
    if [[ "$backup_before_removal" == "true" ]]; then
        create_user_backup "$username"
    fi
    
    # Remove user from system
    sudo dscl . delete /Users/"$username" || {
        log_error "Failed to remove user $username from system"
        return 1
    }
    
    # Update metadata
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    if [[ -f "$metadata_file" ]]; then
        jq '.status = "deleted" | .deleted_date = now | .deleted_by = "'"$(whoami)"'"' "$metadata_file" > "${metadata_file}.tmp" && mv "${metadata_file}.tmp" "$metadata_file"
    fi
    
    # Audit logging
    audit_log "User removed: $username by $(whoami)"
    
    log_action "✅ User $username removed successfully"
    return 0
}

# User backup and restore
create_user_backup() {
    local username="$1"
    local backup_file="$BACKUP_DIR/${username}_backup_$(date +%Y%m%d_%H%M%S).plist"
    
    log_action "Creating backup for user: $username"
    
    # Export user record
    sudo dscl . read /Users/"$username" > "$backup_file"
    
    # Backup metadata
    local metadata_file="$CONFIG_DIR/${username}_metadata.json"
    if [[ -f "$metadata_file" ]]; then
        cp "$metadata_file" "$BACKUP_DIR/${username}_metadata_$(date +%Y%m%d_%H%M%S).json"
    fi
    
    log_action "✅ User backup created: $backup_file"
}

# System health monitoring
monitor_user_system() {
    echo "=== User System Health Check ==="
    
    # Check for expired users
    local expired_users=0
    for metadata_file in "$CONFIG_DIR"/*_metadata.json; do
        if [[ -f "$metadata_file" ]]; then
            local expiry_date username
            expiry_date=$(jq -r '.expiry_date' "$metadata_file")
            username=$(jq -r '.username' "$metadata_file")
            
            if [[ "$expiry_date" != "null" && "$expiry_date" != "" ]]; then
                if [[ $(date -d "$expiry_date" +%s 2>/dev/null) -lt $(date +%s) ]]; then
                    echo "⚠️  Expired user: $username (expired: $expiry_date)"
                    ((expired_users++))
                fi
            fi
        fi
    done
    
    # Check for orphaned user records
    local system_users
    system_users=$(dscl . list /Users | grep -E "^(Sharing|Guest|Service|External)" || true)
    local orphaned_users=0
    
    while IFS= read -r user; do
        if [[ -n "$user" && ! -f "$CONFIG_DIR/${user}_metadata.json" ]]; then
            echo "⚠️  Orphaned user (no metadata): $user"
            ((orphaned_users++))
        fi
    done <<< "$system_users"
    
    # Summary
    echo ""
    echo "Health Summary:"
    echo "  Expired users: $expired_users"
    echo "  Orphaned users: $orphaned_users"
    
    if [[ $expired_users -eq 0 && $orphaned_users -eq 0 ]]; then
        echo "✅ User system is healthy"
    else
        echo "⚠️  User system requires attention"
    fi
}

# Generate comprehensive reports
generate_user_report() {
    local report_name="$1"
    local report_file="$REPORTS_DIR/${report_name}.json"
    
    log_action "Generating user report: $report_name"
    
    # Collect user statistics
    local total_users active_users inactive_users
    total_users=$(find "$CONFIG_DIR" -name "*_metadata.json" | wc -l)
    active_users=$(grep -l '"status": "active"' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | wc -l)
    inactive_users=$((total_users - active_users))
    
    # Category breakdown
    local categories
    categories=$(jq -r '.user_category' "$CONFIG_DIR"/*_metadata.json 2>/dev/null | sort | uniq -c | awk '{print "{\"category\": \"" $2 "\", \"count\": " $1 "}"}' | jq -s '.')
    
    # Generate report
    cat > "$report_file" << EOF
{
    "report_name": "$report_name",
    "generated_date": "$(date -Iseconds)",
    "generated_by": "$(whoami)",
    "hostname": "$(hostname)",
    "statistics": {
        "total_users": $total_users,
        "active_users": $active_users,
        "inactive_users": $inactive_users
    },
    "category_breakdown": $categories,
    "system_info": {
        "macfleet_version": "2025.07.07",
        "os_version": "$(sw_vers -productVersion)",
        "hostname": "$(hostname)"
    }
}
EOF
    
    log_action "✅ Report generated: $report_file"
    echo "Report saved to: $report_file"
}

# Fleet deployment functions
deploy_to_fleet() {
    local fleet_config="$1"
    local user_config="$2"
    
    log_action "Starting fleet deployment"
    
    if [[ ! -f "$fleet_config" ]]; then
        log_error "Fleet configuration file not found: $fleet_config"
        return 1
    fi
    
    if [[ ! -f "$user_config" ]]; then
        log_error "User configuration file not found: $user_config"
        return 1
    fi
    
    # Read fleet configuration
    local hosts
    hosts=$(jq -r '.hosts[]' "$fleet_config")
    
    # Deploy to each host
    while IFS= read -r host; do
        if [[ -n "$host" ]]; then
            log_action "Deploying to host: $host"
            
            # Copy user management script and configuration
            scp "$0" "$user_config" "root@${host}:/tmp/" || {
                log_error "Failed to copy files to $host"
                continue
            }
            
            # Execute deployment on remote host
            ssh "root@${host}" "chmod +x /tmp/$(basename "$0") && /tmp/$(basename "$0") deploy_from_config /tmp/$(basename "$user_config")" || {
                log_error "Failed to execute deployment on $host"
                continue
            }
            
            log_action "✅ Deployment completed on: $host"
        fi
    done <<< "$hosts"
    
    log_action "Fleet deployment completed"
}

# Main function with command routing
main() {
    local command="$1"
    shift
    
    # Initialize
    create_directories
    
    case "$command" in
        "create")
            create_enterprise_user "$@"
            ;;
        "bulk_create")
            bulk_create_users "$@"
            ;;
        "list")
            list_enterprise_users
            ;;
        "remove")
            remove_enterprise_user "$@"
            ;;
        "backup")
            create_user_backup "$@"
            ;;
        "monitor")
            monitor_user_system
            ;;
        "report")
            generate_user_report "$@"
            ;;
        "deploy_fleet")
            deploy_to_fleet "$@"
            ;;
        "show_categories")
            print_user_categories
            ;;
        "show_policies")
            for policy in standard strong basic service department external public; do
                echo "Policy: $policy"
                echo "  $(generate_password_policy "$policy")"
                echo ""
            done
            ;;
        *)
            echo "MacFleet Enterprise User Management System"
            echo "Usage: $0 <command> [options]"
            echo ""
            echo "Commands:"
            echo "  create <username> <display_name> <category> <profile> [department] [expiry]"
            echo "  bulk_create <csv_file>"
            echo "  list"
            echo "  remove <username> [backup_before_removal]"
            echo "  backup <username>"
            echo "  monitor"
            echo "  report <report_name>"
            echo "  deploy_fleet <fleet_config> <user_config>"
            echo "  show_categories"
            echo "  show_policies"
            echo ""
            echo "Examples:"
            echo "  $0 create FileShare 'File Sharing Account' sharing_standard corporate_standard IT"
            echo "  $0 bulk_create users.csv"
            echo "  $0 list"
            echo "  $0 monitor"
            echo "  $0 report monthly_audit"
            ;;
    esac
}

# Execute main function with all arguments
main "$@"

Fleet Deployment Example

CSV Template for Bulk Creation

username,display_name,category,profile,department,expiry
FileShare01,File Sharing Account 1,sharing_standard,corporate_standard,IT,
GuestLobby,Guest Lobby Access,guest_temporary,guest_access_lobby,Reception,2025-12-31
PartnerExt,External Partner Access,sharing_secure,partner_collaboration,Legal,2025-09-30
KioskLib,Library Kiosk Account,kiosk_public,kiosk_public_library,Public,
FinanceShare,Finance Shared Account,sharing_secure,high_security_finance,Finance,
DevTeam,Development Team Share,sharing_standard,research_development,Engineering,

Fleet Configuration Example

{
    "fleet_name": "MacFleet Corporate",
    "deployment_date": "2025-07-07",
    "hosts": [
        "mac-office-01.company.com",
        "mac-office-02.company.com",
        "mac-conference-01.company.com"
    ],
    "deployment_profile": "corporate_standard",
    "security_policy": "enterprise_standard",
    "monitoring": {
        "enabled": true,
        "reporting_interval": "daily",
        "alert_threshold": "high"
    }
}

Security Considerations

User Account Security

  • No Shell Access - Sharing users cannot access command line
  • No Home Directory - Prevents file storage in user directories
  • Limited Group Membership - Restricts system access
  • Password Policies - Enforces strong password requirements
  • Audit Logging - Tracks all user management activities

Enterprise Compliance

  • SOX Compliance - Financial user access controls
  • HIPAA Compliance - Healthcare data protection
  • NIST Framework - Security control implementation
  • ISO 27001 - Information security management

Troubleshooting Guide

Common Issues

User Creation Fails

  • Check if user ID is already in use
  • Verify administrative privileges
  • Ensure directory services are running

Authentication Problems

  • Verify password policy compliance
  • Check user account status
  • Review audit logs for failed attempts

Permission Errors

  • Confirm group memberships
  • Check file sharing permissions
  • Verify security policy application

Diagnostic Commands

# Check user existence
dscl . read /Users/username

# List all users
dscl . list /Users

# Check user groups
groups username

# View user properties
id username

Important Notes

  • Test thoroughly before fleet deployment
  • Backup user data before making changes
  • Monitor audit logs for security events
  • Update policies based on security requirements
  • Document changes for compliance auditing
  • Use secure password delivery methods in production

Tutorial

Novas atualizações e melhorias para a Macfleet.

Configurando um Runner do GitHub Actions em um Mac Mini (Apple Silicon)

Runner do GitHub Actions

GitHub Actions é uma plataforma poderosa de CI/CD que permite automatizar seus fluxos de trabalho de desenvolvimento de software. Embora o GitHub ofereça runners hospedados, runners auto-hospedados fornecem maior controle e personalização para sua configuração de CI/CD. Este tutorial o guia através da configuração e conexão de um runner auto-hospedado em um Mac mini para executar pipelines do macOS.

Pré-requisitos

Antes de começar, certifique-se de ter:

  • Um Mac mini (registre-se no Macfleet)
  • Um repositório GitHub com direitos de administrador
  • Um gerenciador de pacotes instalado (preferencialmente Homebrew)
  • Git instalado em seu sistema

Passo 1: Criar uma Conta de Usuário Dedicada

Primeiro, crie uma conta de usuário dedicada para o runner do GitHub Actions:

# Criar a conta de usuário '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

# Definir a senha para o usuário
sudo dscl . -passwd /Users/gh-runner sua_senha

# Adicionar 'gh-runner' ao grupo 'admin'
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Mude para a nova conta de usuário:

su gh-runner

Passo 2: Instalar Software Necessário

Instale Git e Rosetta 2 (se estiver usando Apple Silicon):

# Instalar Git se ainda não estiver instalado
brew install git

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

Passo 3: Configurar o Runner do GitHub Actions

  1. Vá para seu repositório GitHub
  2. Navegue para Configurações > Actions > Runners

Runner do GitHub Actions

  1. Clique em "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Selecione macOS como imagem do runner e ARM64 como arquitetura
  3. Siga os comandos fornecidos para baixar e configurar o runner

Runner do GitHub Actions

Crie um arquivo .env no diretório _work do runner:

# arquivo _work/.env
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Execute o script run.sh em seu diretório do runner para completar a configuração.
  2. Verifique se o runner está ativo e ouvindo por trabalhos no terminal e verifique as configurações do repositório GitHub para a associação do runner e status Idle.

Runner do GitHub Actions

Passo 4: Configurar Sudoers (Opcional)

Se suas ações requerem privilégios de root, configure o arquivo sudoers:

sudo visudo

Adicione a seguinte linha:

gh-runner ALL=(ALL) NOPASSWD: ALL

Passo 5: Usar o Runner em Fluxos de Trabalho

Configure seu fluxo de trabalho do GitHub Actions para usar o runner auto-hospedado:

name: Fluxo de trabalho de exemplo

on:
  workflow_dispatch:

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

O runner está autenticado em seu repositório e rotulado com self-hosted, macOS, e ARM64. Use-o em seus fluxos de trabalho especificando estes rótulos no campo runs-on:

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

Melhores Práticas

  • Mantenha seu software do runner atualizado
  • Monitore regularmente os logs do runner para problemas
  • Use rótulos específicos para diferentes tipos de runners
  • Implemente medidas de segurança adequadas
  • Considere usar múltiplos runners para balanceamento de carga

Solução de Problemas

Problemas comuns e soluções:

  1. Runner não conectando:

    • Verifique conectividade de rede
    • Verifique validade do token GitHub
    • Certifique-se de permissões adequadas
  2. Falhas de build:

    • Verifique instalação do Xcode
    • Verifique dependências necessárias
    • Revise logs do fluxo de trabalho
  3. Problemas de permissão:

    • Verifique permissões do usuário
    • Verifique configuração sudoers
    • Revise permissões do sistema de arquivos

Conclusão

Agora você tem um runner auto-hospedado do GitHub Actions configurado em seu Mac mini. Esta configuração fornece mais controle sobre seu ambiente CI/CD e permite executar fluxos de trabalho específicos do macOS de forma eficiente.

Lembre-se de manter regularmente seu runner e mantê-lo atualizado com os patches de segurança e versões de software mais recentes.

Aplicativo Nativo

Aplicativo nativo do Macfleet

Guia de Instalação do Macfleet

Macfleet é uma solução poderosa de gerenciamento de frota projetada especificamente para ambientes Mac Mini hospedados na nuvem. Como provedor de hospedagem na nuvem Mac Mini, você pode usar o Macfleet para monitorar, gerenciar e otimizar toda sua frota de instâncias Mac virtualizadas.

Este guia de instalação o conduzirá através da configuração do monitoramento do Macfleet em sistemas macOS, Windows e Linux para garantir supervisão abrangente de sua infraestrutura na nuvem.

🍎 macOS

  • Baixe o arquivo .dmg para Mac aqui
  • Clique duas vezes no arquivo .dmg baixado
  • Arraste o aplicativo Macfleet para a pasta Aplicativos
  • Ejete o arquivo .dmg
  • Abra Preferências do Sistema > Segurança e Privacidade
    • Aba Privacidade > Acessibilidade
    • Marque Macfleet para permitir monitoramento
  • Inicie o Macfleet a partir de Aplicativos
  • O rastreamento inicia automaticamente

🪟 Windows

  • Baixe o arquivo .exe para Windows aqui
  • Clique com o botão direito no arquivo .exe > "Executar como administrador"
  • Siga o assistente de instalação
  • Aceite os termos e condições
  • Permita no Windows Defender se solicitado
  • Conceda permissões de monitoramento de aplicativo
  • Inicie o Macfleet a partir do Menu Iniciar
  • O aplicativo começa o rastreamento automaticamente

🐧 Linux

  • Baixe o pacote .deb (Ubuntu/Debian) ou .rpm (CentOS/RHEL) aqui
  • Instale usando seu gerenciador de pacotes
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Permita permissões de acesso X11 se solicitado
  • Adicione o usuário aos grupos apropriados se necessário
  • Inicie o Macfleet a partir do menu Aplicativos
  • O aplicativo começa o rastreamento automaticamente

Nota: Após a instalação em todos os sistemas, faça login com suas credenciais do Macfleet para sincronizar dados com seu painel de controle.