Tutorial

Neue Updates und Verbesserungen zu Macfleet.

Wichtiger Hinweis

Die in diesen Tutorials bereitgestellten Codebeispiele und Skripte dienen nur zu Bildungszwecken. Macfleet ist nicht verantwortlich für Probleme, Schäden oder Sicherheitslücken, die durch die Verwendung, Änderung oder Implementierung dieser Beispiele entstehen können. Überprüfen und testen Sie Code immer in einer sicheren Umgebung, bevor Sie ihn in Produktionssystemen verwenden.

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

Neue Updates und Verbesserungen zu Macfleet.

Konfiguration eines GitHub Actions Runners auf einem Mac Mini (Apple Silicon)

GitHub Actions Runner

GitHub Actions ist eine leistungsstarke CI/CD-Plattform, die es Ihnen ermöglicht, Ihre Software-Entwicklungsworkflows zu automatisieren. Während GitHub gehostete Runner anbietet, bieten selbst-gehostete Runner erhöhte Kontrolle und Anpassung für Ihr CI/CD-Setup. Dieses Tutorial führt Sie durch die Einrichtung, Konfiguration und Verbindung eines selbst-gehosteten Runners auf einem Mac mini zur Ausführung von macOS-Pipelines.

Voraussetzungen

Bevor Sie beginnen, stellen Sie sicher, dass Sie haben:

  • Einen Mac mini (registrieren Sie sich bei Macfleet)
  • Ein GitHub-Repository mit Administratorrechten
  • Einen installierten Paketmanager (vorzugsweise Homebrew)
  • Git auf Ihrem System installiert

Schritt 1: Ein dediziertes Benutzerkonto erstellen

Erstellen Sie zunächst ein dediziertes Benutzerkonto für den GitHub Actions Runner:

# Das 'gh-runner' Benutzerkonto erstellen
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

# Das Passwort für den Benutzer setzen
sudo dscl . -passwd /Users/gh-runner ihr_passwort

# 'gh-runner' zur 'admin'-Gruppe hinzufügen
sudo dscl . -append /Groups/admin GroupMembership gh-runner

Wechseln Sie zum neuen Benutzerkonto:

su gh-runner

Schritt 2: Erforderliche Software installieren

Installieren Sie Git und Rosetta 2 (wenn Sie Apple Silicon verwenden):

# Git installieren, falls noch nicht installiert
brew install git

# Rosetta 2 für Apple Silicon Macs installieren
softwareupdate --install-rosetta

Schritt 3: Den GitHub Actions Runner konfigurieren

  1. Gehen Sie zu Ihrem GitHub-Repository
  2. Navigieren Sie zu Einstellungen > Actions > Runners

GitHub Actions Runner

  1. Klicken Sie auf "New self-hosted runner" (https://github.com/<username>/<repository>/settings/actions/runners/new)
  2. Wählen Sie macOS als Runner-Image und ARM64 als Architektur
  3. Folgen Sie den bereitgestellten Befehlen, um den Runner herunterzuladen und zu konfigurieren

GitHub Actions Runner

Erstellen Sie eine .env-Datei im _work-Verzeichnis des Runners:

# _work/.env Datei
ImageOS=macos15
XCODE_15_DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer
  1. Führen Sie das run.sh-Skript in Ihrem Runner-Verzeichnis aus, um die Einrichtung abzuschließen.
  2. Überprüfen Sie, dass der Runner aktiv ist und auf Jobs im Terminal wartet, und überprüfen Sie die GitHub-Repository-Einstellungen für die Runner-Zuordnung und den Idle-Status.

GitHub Actions Runner

Schritt 4: Sudoers konfigurieren (Optional)

Wenn Ihre Actions Root-Privilegien benötigen, konfigurieren Sie die sudoers-Datei:

sudo visudo

Fügen Sie die folgende Zeile hinzu:

gh-runner ALL=(ALL) NOPASSWD: ALL

Schritt 5: Den Runner in Workflows verwenden

Konfigurieren Sie Ihren GitHub Actions Workflow, um den selbst-gehosteten Runner zu verwenden:

name: Beispiel-Workflow

on:
  workflow_dispatch:

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

Der Runner ist bei Ihrem Repository authentifiziert und mit self-hosted, macOS und ARM64 markiert. Verwenden Sie ihn in Ihren Workflows, indem Sie diese Labels im runs-on-Feld angeben:

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

Best Practices

  • Halten Sie Ihre Runner-Software auf dem neuesten Stand
  • Überwachen Sie regelmäßig Runner-Logs auf Probleme
  • Verwenden Sie spezifische Labels für verschiedene Runner-Typen
  • Implementieren Sie angemessene Sicherheitsmaßnahmen
  • Erwägen Sie die Verwendung mehrerer Runner für Lastverteilung

Fehlerbehebung

Häufige Probleme und Lösungen:

  1. Runner verbindet sich nicht:

    • Überprüfen Sie die Netzwerkverbindung
    • Überprüfen Sie die Gültigkeit des GitHub-Tokens
    • Stellen Sie angemessene Berechtigungen sicher
  2. Build-Fehler:

    • Überprüfen Sie die Xcode-Installation
    • Überprüfen Sie erforderliche Abhängigkeiten
    • Überprüfen Sie Workflow-Logs
  3. Berechtigungsprobleme:

    • Überprüfen Sie Benutzerberechtigungen
    • Überprüfen Sie sudoers-Konfiguration
    • Überprüfen Sie Dateisystem-Berechtigungen

Fazit

Sie haben jetzt einen selbst-gehosteten GitHub Actions Runner auf Ihrem Mac mini konfiguriert. Diese Einrichtung bietet Ihnen mehr Kontrolle über Ihre CI/CD-Umgebung und ermöglicht es Ihnen, macOS-spezifische Workflows effizient auszuführen.

Denken Sie daran, Ihren Runner regelmäßig zu warten und ihn mit den neuesten Sicherheitspatches und Software-Versionen auf dem neuesten Stand zu halten.

Native App

Macfleet native App

Macfleet Installationsanleitung

Macfleet ist eine leistungsstarke Flottenmanagement-Lösung, die speziell für Cloud-gehostete Mac Mini-Umgebungen entwickelt wurde. Als Mac Mini Cloud-Hosting-Anbieter können Sie Macfleet verwenden, um Ihre gesamte Flotte virtualisierter Mac-Instanzen zu überwachen, zu verwalten und zu optimieren.

Diese Installationsanleitung führt Sie durch die Einrichtung der Macfleet-Überwachung auf macOS-, Windows- und Linux-Systemen, um eine umfassende Übersicht über Ihre Cloud-Infrastruktur zu gewährleisten.

🍎 macOS

  • Laden Sie die .dmg-Datei für Mac hier herunter
  • Doppelklicken Sie auf die heruntergeladene .dmg-Datei
  • Ziehen Sie die Macfleet-App in den Anwendungsordner
  • Werfen Sie die .dmg-Datei aus
  • Öffnen Sie Systemeinstellungen > Sicherheit & Datenschutz
    • Datenschutz-Tab > Bedienungshilfen
    • Aktivieren Sie Macfleet, um Überwachung zu erlauben
  • Starten Sie Macfleet aus den Anwendungen
  • Die Verfolgung startet automatisch

🪟 Windows

  • Laden Sie die .exe-Datei für Windows hier herunter
  • Rechtsklick auf die .exe-Datei > "Als Administrator ausführen"
  • Folgen Sie dem Installationsassistenten
  • Akzeptieren Sie die Allgemeinen Geschäftsbedingungen
  • Erlauben Sie in Windows Defender, wenn aufgefordert
  • Gewähren Sie Anwendungsüberwachungsberechtigungen
  • Starten Sie Macfleet aus dem Startmenü
  • Die Anwendung beginnt automatisch mit der Verfolgung

🐧 Linux

  • Laden Sie das .deb-Paket (Ubuntu/Debian) oder .rpm (CentOS/RHEL) hier herunter
  • Installieren Sie mit Ihrem Paketmanager
    • Ubuntu/Debian: sudo dpkg -i Macfleet-linux.deb
    • CentOS/RHEL: sudo rpm -ivh Macfleet-linux.rpm
  • Erlauben Sie X11-Zugriffsberechtigungen, wenn aufgefordert
  • Fügen Sie den Benutzer zu entsprechenden Gruppen hinzu, falls erforderlich
  • Starten Sie Macfleet aus dem Anwendungsmenü
  • Die Anwendung beginnt automatisch mit der Verfolgung

Hinweis: Nach der Installation auf allen Systemen melden Sie sich mit Ihren Macfleet-Anmeldedaten an, um Daten mit Ihrem Dashboard zu synchronisieren.