Tutorial

Nuevas actualizaciones y mejoras para Roundfleet.

Aviso importante

Los ejemplos de código y scripts proporcionados en estos tutoriales son solo para propósitos educativos. Roundfleet 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.

Device Naming and Identity Management on macOS

Implement enterprise-grade device naming and identity management across your Roundfleet deployment with standardized naming conventions, automated provisioning, and comprehensive identity validation. This tutorial provides solutions for maintaining consistent device identification and network presence.

Understanding macOS Device Identity

macOS devices have three distinct naming components that affect identification and network behavior:

  • Computer Name - User-friendly name displayed in Sharing preferences and Finder
  • Local Host Name - Network identifier with ".local" suffix for Bonjour/mDNS
  • Hostname - Primary network hostname used in terminal and network services
  • NetBIOS Name - Windows network compatibility identifier

Basic Device Naming Operations

Change Computer Name

#!/bin/bash

# Set computer name
scutil --set ComputerName "$ComputerName"

echo "Computer name set to: $ComputerName"

Change Local Host Name

#!/bin/bash

# Set local hostname for Bonjour/mDNS discovery
scutil --set LocalHostName "$LocalHostName"

echo "Local hostname set to: $LocalHostName"

Change Hostname

#!/bin/bash

# Set primary hostname for network services
# Example: Your-iMac.domain.com
scutil --set HostName "$HostName"

echo "Hostname set to: $HostName"

Flush DNS Cache

#!/bin/bash

# Flush DNS cache after name changes
sudo dscacheutil --flushcache

echo "DNS cache flushed successfully"

Enterprise Naming Standards

Standardized Naming Convention Script

#!/bin/bash

# Roundfleet Enterprise Device Naming Tool
# Implements standardized naming conventions across fleet

# Configuration
CONFIG_FILE="/etc/roundfleet/naming_policy.conf"
LOG_FILE="/var/log/roundfleet_naming.log"
REPORT_DIR="/var/log/roundfleet_reports"

# Create directories
mkdir -p "$(dirname "$CONFIG_FILE")" "$(dirname "$LOG_FILE")" "$REPORT_DIR"

# Default naming policy
cat > "$CONFIG_FILE" 2>/dev/null << 'EOF' || true
# Roundfleet Device Naming Policy
# Version: 2.0

# Naming Convention Format
# Pattern: {PREFIX}-{LOCATION}-{TYPE}-{SEQUENCE}
# Example: MF-NYC-MBP-001

# Organization Settings
ORG_PREFIX="MF"
DOMAIN_SUFFIX="roundfleet.local"
ENABLE_AUTO_NAMING=true
VALIDATE_NAMES=true

# Location Codes
LOCATION_CODES="NYC,SF,LA,CHI,BOS,SEA,ATL,MIA"
DEFAULT_LOCATION="NYC"

# Device Type Mapping
# Format: MODEL_IDENTIFIER:SHORT_CODE
DEVICE_TYPES=(
    "MacBookPro:MBP"
    "MacBookAir:MBA"
    "iMac:iMac"
    "iMacPro:iMP"
    "MacPro:MP"
    "Macmini:MM"
    "MacStudio:MS"
)

# Network Settings
ENABLE_NETBIOS=true
SYNC_ALL_NAMES=true
FLUSH_DNS_AFTER_CHANGE=true
EOF

# Source configuration
source "$CONFIG_FILE" 2>/dev/null || true

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

# Get device model information
get_device_model() {
    local model_identifier
    model_identifier=$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)
    
    # Map model to device type
    for mapping in "${DEVICE_TYPES[@]}"; do
        local model_pattern="${mapping%:*}"
        local type_code="${mapping#*:}"
        
        if [[ "$model_identifier" == *"$model_pattern"* ]]; then
            echo "$type_code"
            return 0
        fi
    done
    
    # Default fallback
    echo "MAC"
}

# Get location from user input or configuration
get_location_code() {
    local location="$1"
    
    if [[ -z "$location" ]]; then
        location="$DEFAULT_LOCATION"
    fi
    
    # Validate location code
    if [[ ",$LOCATION_CODES," == *",$location,"* ]]; then
        echo "$location"
    else
        echo "$DEFAULT_LOCATION"
        log_action "WARNING: Invalid location '$location', using default '$DEFAULT_LOCATION'"
    fi
}

# Generate sequence number
generate_sequence() {
    local prefix="$1"
    local sequence_file="/var/lib/roundfleet/sequences/${prefix}.seq"
    
    mkdir -p "$(dirname "$sequence_file")"
    
    if [[ -f "$sequence_file" ]]; then
        local current_seq
        current_seq=$(cat "$sequence_file")
        ((current_seq++))
    else
        current_seq=1
    fi
    
    printf "%03d" "$current_seq" > "$sequence_file"
    printf "%03d" "$current_seq"
}

# Generate standardized device name
generate_device_name() {
    local location="$1"
    local custom_suffix="$2"
    
    local device_type
    device_type=$(get_device_model)
    
    local location_code
    location_code=$(get_location_code "$location")
    
    local base_prefix="${ORG_PREFIX}-${location_code}-${device_type}"
    
    if [[ -n "$custom_suffix" ]]; then
        echo "${base_prefix}-${custom_suffix}"
    else
        local sequence
        sequence=$(generate_sequence "$base_prefix")
        echo "${base_prefix}-${sequence}"
    fi
}

# Validate naming compliance
validate_device_name() {
    local name="$1"
    local errors=()
    
    # Length validation
    if [[ ${#name} -gt 15 ]]; then
        errors+=("Name too long (max 15 characters for NetBIOS compatibility)")
    fi
    
    # Character validation
    if [[ "$name" =~ [^A-Za-z0-9\-] ]]; then
        errors+=("Invalid characters (only alphanumeric and hyphens allowed)")
    fi
    
    # Format validation
    if [[ ! "$name" =~ ^[A-Z]{2,4}-[A-Z]{2,4}-[A-Z]{2,4}-[0-9]{3}$ ]] && [[ "$VALIDATE_NAMES" == "true" ]]; then
        errors+=("Name doesn't match organization standard format")
    fi
    
    if [[ ${#errors[@]} -eq 0 ]]; then
        return 0
    else
        printf '%s\n' "${errors[@]}"
        return 1
    fi
}

# Apply device names with validation
apply_device_names() {
    local computer_name="$1"
    local hostname="$2"
    local local_hostname="$3"
    
    echo "=== Applying Device Names ==="
    
    # Validate all names
    local validation_errors=0
    
    if ! validate_device_name "$computer_name"; then
        echo "❌ Computer name validation failed"
        ((validation_errors++))
    fi
    
    if [[ -n "$hostname" ]] && ! validate_device_name "${hostname%%.*}"; then
        echo "❌ Hostname validation failed"
        ((validation_errors++))
    fi
    
    if [[ -n "$local_hostname" ]] && ! validate_device_name "$local_hostname"; then
        echo "❌ Local hostname validation failed"
        ((validation_errors++))
    fi
    
    if [[ $validation_errors -gt 0 ]] && [[ "$VALIDATE_NAMES" == "true" ]]; then
        echo "⚠️  Name validation failed, aborting changes"
        return 1
    fi
    
    # Apply computer name
    if [[ -n "$computer_name" ]]; then
        scutil --set ComputerName "$computer_name"
        echo "✅ Computer name: $computer_name"
        log_action "Computer name changed to: $computer_name"
    fi
    
    # Apply hostname
    if [[ -n "$hostname" ]]; then
        scutil --set HostName "$hostname"
        echo "✅ Hostname: $hostname"
        log_action "Hostname changed to: $hostname"
    fi
    
    # Apply local hostname
    if [[ -n "$local_hostname" ]]; then
        scutil --set LocalHostName "$local_hostname"
        echo "✅ Local hostname: $local_hostname"
        log_action "Local hostname changed to: $local_hostname"
    fi
    
    # Apply NetBIOS name if enabled
    if [[ "$ENABLE_NETBIOS" == "true" ]] && [[ -n "$computer_name" ]]; then
        defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$computer_name"
        echo "✅ NetBIOS name: $computer_name"
        log_action "NetBIOS name changed to: $computer_name"
    fi
    
    # Flush DNS cache
    if [[ "$FLUSH_DNS_AFTER_CHANGE" == "true" ]]; then
        sudo dscacheutil --flushcache
        echo "✅ DNS cache flushed"
        log_action "DNS cache flushed after name changes"
    fi
    
    return 0
}

# Auto-generate and apply names
auto_provision_device() {
    local location="$1"
    local custom_suffix="$2"
    
    echo "=== Auto-Provisioning Device Names ==="
    
    if [[ "$ENABLE_AUTO_NAMING" != "true" ]]; then
        echo "❌ Auto-naming disabled in policy"
        return 1
    fi
    
    # Generate base name
    local base_name
    base_name=$(generate_device_name "$location" "$custom_suffix")
    
    # Create all naming variants
    local computer_name="$base_name"
    local local_hostname="$base_name"
    local hostname="${base_name}.${DOMAIN_SUFFIX}"
    
    echo "Generated names:"
    echo "  Computer Name: $computer_name"
    echo "  Local Hostname: $local_hostname"
    echo "  Hostname: $hostname"
    echo ""
    
    # Apply names
    apply_device_names "$computer_name" "$hostname" "$local_hostname"
}

# Get current device identity
get_current_identity() {
    echo "=== Current Device Identity ==="
    
    local computer_name
    computer_name=$(scutil --get ComputerName 2>/dev/null || echo "Not Set")
    
    local hostname
    hostname=$(scutil --get HostName 2>/dev/null || echo "Not Set")
    
    local local_hostname
    local_hostname=$(scutil --get LocalHostName 2>/dev/null || echo "Not Set")
    
    local netbios_name
    netbios_name=$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName 2>/dev/null || echo "Not Set")
    
    echo "Computer Name: $computer_name"
    echo "Hostname: $hostname"
    echo "Local Hostname: $local_hostname"
    echo "NetBIOS Name: $netbios_name"
    echo "Serial Number: $(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)"
    echo "Model: $(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)"
}

# Generate compliance report
generate_naming_report() {
    local report_file="$REPORT_DIR/device_naming_$(date +%Y%m%d_%H%M%S).json"
    
    echo "=== Generating Naming Compliance Report ==="
    
    local computer_name hostname local_hostname netbios_name
    computer_name=$(scutil --get ComputerName 2>/dev/null || echo "")
    hostname=$(scutil --get HostName 2>/dev/null || echo "")
    local_hostname=$(scutil --get LocalHostName 2>/dev/null || echo "")
    netbios_name=$(defaults read /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName 2>/dev/null || echo "")
    
    # Check compliance
    local computer_compliant="false"
    local hostname_compliant="false"
    local naming_compliant="false"
    
    if validate_device_name "$computer_name" >/dev/null 2>&1; then
        computer_compliant="true"
    fi
    
    if [[ -n "$hostname" ]] && validate_device_name "${hostname%%.*}" >/dev/null 2>&1; then
        hostname_compliant="true"
    fi
    
    if [[ "$computer_compliant" == "true" ]] && [[ "$hostname_compliant" == "true" ]]; then
        naming_compliant="true"
    fi
    
    # Create JSON report
    cat > "$report_file" << EOF
{
  "report_type": "device_naming_compliance",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "device_info": {
    "hostname": "$(hostname)",
    "serial_number": "$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)",
    "model_identifier": "$(system_profiler SPHardwareDataType | grep "Model Identifier" | awk -F: '{print $2}' | xargs)",
    "macos_version": "$(sw_vers -productVersion)"
  },
  "current_names": {
    "computer_name": "$computer_name",
    "hostname": "$hostname",
    "local_hostname": "$local_hostname",
    "netbios_name": "$netbios_name"
  },
  "compliance": {
    "computer_name_compliant": $computer_compliant,
    "hostname_compliant": $hostname_compliant,
    "overall_compliant": $naming_compliant,
    "policy_version": "2.0"
  },
  "policy_settings": {
    "org_prefix": "$ORG_PREFIX",
    "domain_suffix": "$DOMAIN_SUFFIX",
    "auto_naming_enabled": $ENABLE_AUTO_NAMING,
    "validation_enabled": $VALIDATE_NAMES
  }
}
EOF
    
    echo "Naming report saved to: $report_file"
    log_action "Device naming report generated: $report_file"
}

# Main function with argument handling
main() {
    log_action "=== Roundfleet Device Naming Tool Started ==="
    
    case "${1:-status}" in
        "auto-provision")
            auto_provision_device "$2" "$3"
            ;;
        "set-names")
            apply_device_names "$2" "$3" "$4"
            ;;
        "validate")
            get_current_identity
            echo ""
            if validate_device_name "$2" 2>/dev/null; then
                echo "✅ Name '$2' is compliant"
            else
                echo "❌ Name '$2' validation failed:"
                validate_device_name "$2"
            fi
            ;;
        "report")
            generate_naming_report
            ;;
        "status"|*)
            get_current_identity
            ;;
    esac
    
    log_action "=== Device naming operation completed ==="
}

# Execute main function
main "$@"

Advanced Identity Management

Network Identity Synchronization

#!/bin/bash

# Synchronize all naming components for consistency
sync_network_identity() {
    echo "=== Network Identity Synchronization ==="
    
    # Get current computer name as source
    local source_name
    source_name=$(scutil --get ComputerName 2>/dev/null)
    
    if [[ -z "$source_name" ]]; then
        echo "❌ No computer name set, cannot synchronize"
        return 1
    fi
    
    # Generate consistent names
    local clean_name
    clean_name=$(echo "$source_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
    
    local local_hostname="$clean_name"
    local hostname="${clean_name}.local"
    
    echo "Synchronizing identity from: $source_name"
    echo "Local Hostname: $local_hostname"
    echo "Hostname: $hostname"
    
    # Apply synchronized names
    scutil --set LocalHostName "$local_hostname"
    scutil --set HostName "$hostname"
    
    # Update NetBIOS
    defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$source_name"
    
    # Flush DNS cache
    sudo dscacheutil --flushcache
    
    echo "✅ Network identity synchronized"
}

sync_network_identity

Bulk Device Provisioning

#!/bin/bash

# Bulk device naming for fleet deployment
bulk_provision_devices() {
    local csv_file="$1"
    local report_file="/tmp/bulk_naming_$(date +%Y%m%d_%H%M%S).csv"
    
    echo "=== Bulk Device Provisioning ==="
    echo "Serial,Computer_Name,Hostname,Status,Timestamp" > "$report_file"
    
    # Read CSV file with device assignments
    # Format: Serial,Location,CustomSuffix
    while IFS=',' read -r serial location suffix; do
        # Skip header
        [[ "$serial" == "Serial" ]] && continue
        
        local current_serial
        current_serial=$(system_profiler SPHardwareDataType | grep "Serial Number" | awk -F: '{print $2}' | xargs)
        
        if [[ "$current_serial" == "$serial" ]]; then
            echo "Processing device: $serial"
            
            # Generate names for this device
            local device_name
            device_name=$(generate_device_name "$location" "$suffix")
            
            local computer_name="$device_name"
            local hostname="${device_name}.roundfleet.local"
            
            # Apply names
            if apply_device_names "$computer_name" "$hostname" "$device_name"; then
                echo "$serial,$computer_name,$hostname,SUCCESS,$(date)" >> "$report_file"
                echo "✅ Successfully provisioned: $computer_name"
            else
                echo "$serial,$computer_name,$hostname,FAILED,$(date)" >> "$report_file"
                echo "❌ Failed to provision: $computer_name"
            fi
            
            break
        fi
    done < "$csv_file"
    
    echo "Bulk provisioning report: $report_file"
}

# Example usage:
# bulk_provision_devices "/path/to/device_assignments.csv"

Identity Validation and Compliance

Comprehensive Validation Script

#!/bin/bash

# Complete device identity validation
validate_device_identity() {
    echo "=== Device Identity Validation ==="
    
    local issues=0
    local warnings=0
    
    # Get all current names
    local computer_name hostname local_hostname
    computer_name=$(scutil --get ComputerName 2>/dev/null)
    hostname=$(scutil --get HostName 2>/dev/null)
    local_hostname=$(scutil --get LocalHostName 2>/dev/null)
    
    # Computer name validation
    if [[ -z "$computer_name" ]]; then
        echo "❌ Computer name not set"
        ((issues++))
    elif ! validate_device_name "$computer_name" >/dev/null 2>&1; then
        echo "⚠️  Computer name format non-compliant: $computer_name"
        ((warnings++))
    else
        echo "✅ Computer name compliant: $computer_name"
    fi
    
    # Hostname validation
    if [[ -z "$hostname" ]]; then
        echo "⚠️  Hostname not set"
        ((warnings++))
    elif ! validate_device_name "${hostname%%.*}" >/dev/null 2>&1; then
        echo "⚠️  Hostname format non-compliant: $hostname"
        ((warnings++))
    else
        echo "✅ Hostname compliant: $hostname"
    fi
    
    # Local hostname validation
    if [[ -z "$local_hostname" ]]; then
        echo "⚠️  Local hostname not set"
        ((warnings++))
    elif ! validate_device_name "$local_hostname" >/dev/null 2>&1; then
        echo "⚠️  Local hostname format non-compliant: $local_hostname"
        ((warnings++))
    else
        echo "✅ Local hostname compliant: $local_hostname"
    fi
    
    # Consistency check
    if [[ -n "$computer_name" && -n "$local_hostname" ]]; then
        local expected_local
        expected_local=$(echo "$computer_name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
        
        if [[ "$local_hostname" != "$expected_local" ]]; then
            echo "⚠️  Names not synchronized (Computer: $computer_name, Local: $local_hostname)"
            ((warnings++))
        fi
    fi
    
    # Network connectivity validation
    echo ""
    echo "=== Network Identity Testing ==="
    
    # Test Bonjour resolution
    if ping -c 1 "${local_hostname}.local" >/dev/null 2>&1; then
        echo "✅ Bonjour resolution working"
    else
        echo "⚠️  Bonjour resolution failed"
        ((warnings++))
    fi
    
    # Test hostname resolution
    if [[ -n "$hostname" ]] && ping -c 1 "$hostname" >/dev/null 2>&1; then
        echo "✅ Hostname resolution working"
    elif [[ -n "$hostname" ]]; then
        echo "⚠️  Hostname resolution failed"
        ((warnings++))
    fi
    
    # Summary
    echo ""
    echo "=== Validation Summary ==="
    echo "Issues: $issues"
    echo "Warnings: $warnings"
    
    if [[ $issues -eq 0 && $warnings -eq 0 ]]; then
        echo "✅ Device identity fully compliant"
        return 0
    elif [[ $issues -eq 0 ]]; then
        echo "⚠️  Device identity has warnings but is functional"
        return 1
    else
        echo "❌ Device identity has critical issues"
        return 2
    fi
}

validate_device_identity

Network Service Integration

DNS and Directory Services

#!/bin/bash

# Update DNS and directory service entries
update_network_services() {
    echo "=== Network Services Update ==="
    
    # Get current names
    local computer_name hostname
    computer_name=$(scutil --get ComputerName 2>/dev/null)
    hostname=$(scutil --get HostName 2>/dev/null)
    
    # Update mDNSResponder
    echo "Restarting mDNSResponder..."
    sudo launchctl kickstart -k system/com.apple.mDNSResponder
    
    # Update NetBIOS registration
    if [[ -n "$computer_name" ]]; then
        echo "Updating NetBIOS registration..."
        defaults write /Library/Preferences/SystemConfiguration/com.apple.smb.server NetBIOSName "$computer_name"
        sudo launchctl kickstart -k system/com.apple.smbd
    fi
    
    # Flush all caches
    echo "Flushing system caches..."
    sudo dscacheutil --flushcache
    sudo killall -HUP mDNSResponder
    
    # Update Open Directory if bound
    if dsconfigldap -v >/dev/null 2>&1; then
        echo "Updating Open Directory registration..."
        sudo dsconfigldap -f
    fi
    
    echo "✅ Network services updated"
}

update_network_services

Important Configuration Notes

System Configuration Utility (scutil)

The scutil command manages macOS system configuration:

  • ComputerName - User-visible device name
  • HostName - Primary network hostname
  • LocalHostName - Bonjour/mDNS identifier
  • NetBIOSName - Windows network compatibility

Best Practices for Enterprise

  1. Standardized Naming Convention

    • Use consistent format: ORG-LOCATION-TYPE-SEQUENCE
    • Keep names under 15 characters for NetBIOS compatibility
    • Avoid special characters and spaces
  2. Network Considerations

    • Ensure unique names across network segments
    • Test DNS resolution after changes
    • Coordinate with network administrators
  3. Fleet Management

    • Implement automated provisioning
    • Maintain naming databases
    • Regular compliance auditing
    • Backup configuration before changes
  4. Security Implications

    • Device names may reveal organizational structure
    • Consider privacy requirements
    • Implement access controls for naming changes

Troubleshooting Common Issues

  • Name changes not taking effect - Restart networking services or reboot
  • Bonjour conflicts - Ensure unique LocalHostName values
  • DNS resolution issues - Flush cache and restart mDNSResponder
  • Windows network problems - Verify NetBIOS name configuration

Remember to test naming changes thoroughly and coordinate with network administrators before implementing across your Roundfleet deployment.