Password Enforcement on macOS
Enforce enterprise-grade password policies and security standards across your MacFleet devices using comprehensive command-line tools and security frameworks. This tutorial covers password policy implementation, compliance monitoring, and automated enforcement systems.
Understanding macOS Password Security
macOS provides multiple layers of password security:
- Password Policies - Complexity, length, and rotation requirements
- Screen Lock Security - Automatic locking and unlock requirements
- Secure Token Management - FileVault and encryption support
- Account Security - User privilege and access controls
Password Policy Configuration
Basic Password Requirements
#!/bin/bash
# Set basic password policy using pwpolicy
configure_password_policy() {
# Configure password complexity requirements
sudo pwpolicy -a diradmin -u $USER -setpolicy "minChars=8 requiresAlpha requiresNumeric"
# Set password history (prevent reuse of last 5 passwords)
sudo pwpolicy -a diradmin -u $USER -setpolicy "usingHistory=5"
# Set password expiration (90 days)
sudo pwpolicy -a diradmin -u $USER -setpolicy "maxMinutesUntilChangePassword=129600"
echo "Basic password policy configured successfully"
}
configure_password_policy
Advanced Security Settings
#!/bin/bash
# Configure advanced password and security settings
configure_advanced_security() {
echo "=== Advanced Security Configuration ==="
# Enable password requirement for wake from sleep
osascript -e 'tell application "System Events" to set require password to wake of security preferences to true'
# Set immediate password requirement
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
# Configure account lockout policy
sudo pwpolicy -a diradmin -setpolicy "maxFailedLoginAttempts=5"
# Enable automatic logout after inactivity
sudo defaults write /Library/Preferences/.GlobalPreferences com.apple.autologout.AutoLogOutDelay -int 3600
echo "Advanced security settings configured"
}
configure_advanced_security
Screen Lock Enforcement
Automatic Screen Lock
#!/bin/bash
# Configure automatic screen lock settings
configure_screen_lock() {
local lock_delay="${1:-300}" # Default 5 minutes
echo "Configuring screen lock with ${lock_delay} second delay"
# Set screen saver activation time
defaults -currentHost write com.apple.screensaver idleTime -int "$lock_delay"
# Enable password requirement for screen saver
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
# Configure energy saver settings
sudo pmset -a displaysleep 5 # Display sleep after 5 minutes
sudo pmset -a sleep 30 # System sleep after 30 minutes
# Kill screen saver preferences to apply changes
killall ScreenSaverEngine 2>/dev/null || true
echo "Screen lock configured successfully"
}
# Usage: configure_screen_lock [delay_in_seconds]
configure_screen_lock 300
Immediate Lock Enforcement
#!/bin/bash
# Force immediate screen lock
force_screen_lock() {
echo "Forcing immediate screen lock..."
# Multiple methods to ensure lock
/System/Library/CoreServices/Menu\ Extras/User.menu/Contents/Resources/CGSession -suspend
# Alternative method using pmset
pmset displaysleepnow
# Activate screen saver as backup
/System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine.app/Contents/MacOS/ScreenSaverEngine -background &
echo "Screen locked successfully"
}
force_screen_lock
Password Complexity Enforcement
Complex Password Validation
#!/bin/bash
# Validate password complexity
validate_password_complexity() {
local password="$1"
local min_length=8
local errors=0
echo "=== Password Complexity Validation ==="
# Check minimum length
if [[ ${#password} -lt $min_length ]]; then
echo "❌ Password must be at least $min_length characters"
((errors++))
else
echo "✅ Length requirement met"
fi
# Check for uppercase letter
if [[ ! "$password" =~ [A-Z] ]]; then
echo "❌ Password must contain at least one uppercase letter"
((errors++))
else
echo "✅ Uppercase letter found"
fi
# Check for lowercase letter
if [[ ! "$password" =~ [a-z] ]]; then
echo "❌ Password must contain at least one lowercase letter"
((errors++))
else
echo "✅ Lowercase letter found"
fi
# Check for number
if [[ ! "$password" =~ [0-9] ]]; then
echo "❌ Password must contain at least one number"
((errors++))
else
echo "✅ Number found"
fi
# Check for special character
if [[ ! "$password" =~ [^a-zA-Z0-9] ]]; then
echo "❌ Password must contain at least one special character"
((errors++))
else
echo "✅ Special character found"
fi
# Check for common patterns
if [[ "$password" =~ (123|abc|password|qwerty) ]]; then
echo "❌ Password contains common patterns"
((errors++))
else
echo "✅ No common patterns detected"
fi
if [[ $errors -eq 0 ]]; then
echo "✅ Password meets all complexity requirements"
return 0
else
echo "❌ Password failed $errors complexity checks"
return 1
fi
}
# Example usage (do not use in production with actual passwords)
# validate_password_complexity "TestPassword123!"
Password Generation
#!/bin/bash
# Generate secure passwords
generate_secure_password() {
local length="${1:-12}"
local include_symbols="${2:-true}"
echo "=== Secure Password Generation ==="
if [[ "$include_symbols" == "true" ]]; then
# Generate password with symbols
local charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*'
else
# Generate alphanumeric password
local charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
fi
# Generate random password
local password=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-${length})
# Ensure complexity requirements
password="${password:0:$((length-4))}A1@z"
echo "Generated password length: ${#password}"
echo "Password complexity verified"
# Validate the generated password
if validate_password_complexity "$password"; then
echo "✅ Generated password meets all requirements"
fi
}
generate_secure_password 12 true
User Account Management
Password Reset and Management
#!/bin/bash
# User account password management
manage_user_passwords() {
local username="$1"
local action="$2"
echo "=== User Password Management ==="
echo "Managing password for user: $username"
case "$action" in
"reset")
# Force password reset on next login
sudo pwpolicy -a diradmin -u "$username" -setpolicy "newPasswordRequired=1"
echo "Password reset required for $username on next login"
;;
"expire")
# Expire password immediately
sudo pwpolicy -a diradmin -u "$username" -setpolicy "passwordLastSetTime=0"
echo "Password expired for $username"
;;
"unlock")
# Unlock account after failed attempts
sudo pwpolicy -a diradmin -u "$username" -clearfailedlogins
echo "Account unlocked for $username"
;;
"status")
# Check password status
sudo pwpolicy -a diradmin -u "$username" -getpolicy
;;
*)
echo "Usage: manage_user_passwords <username> <reset|expire|unlock|status>"
return 1
;;
esac
}
# Example usage
# manage_user_passwords "johndoe" "status"
Secure Token Management
#!/bin/bash
# Add secure token to user account
add_secure_token() {
local admin_user="$1"
local admin_password="$2"
local target_user="$3"
local target_password="$4"
echo "=== Secure Token Management ==="
# Check macOS version compatibility
local macos_version=$(sw_vers -productVersion)
echo "macOS Version: $macos_version"
# Check if target user already has secure token
if sysadminctl -secureTokenStatus "$target_user" 2>&1 | grep -q "ENABLED"; then
echo "✅ $target_user already has SecureToken"
return 0
fi
# Check if admin user has secure token
if sysadminctl -secureTokenStatus "$admin_user" 2>&1 | grep -q "DISABLED"; then
echo "❌ Admin user $admin_user does not have SecureToken"
return 1
fi
echo "Adding SecureToken to $target_user..."
# Add secure token
if sysadminctl -adminUser "$admin_user" \
-adminPassword "$admin_password" \
-secureTokenOn "$target_user" \
-password "$target_password"; then
echo "✅ SecureToken added successfully to $target_user"
else
echo "❌ Failed to add SecureToken to $target_user"
return 1
fi
}
# Example usage (replace with actual credentials in secure environment)
# add_secure_token "admin" "admin_pass" "user" "user_pass"
Enterprise Password Management System
#!/bin/bash
# MacFleet Enterprise Password Management System
# Comprehensive password policy enforcement and monitoring
# Configuration
LOG_FILE="/var/log/macfleet_password_security.log"
POLICY_CONFIG="/etc/macfleet/password_policy.conf"
COMPLIANCE_REPORT="/var/log/macfleet_password_compliance.json"
# Logging function
log_action() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Load password policy configuration
load_policy_config() {
if [[ -f "$POLICY_CONFIG" ]]; then
source "$POLICY_CONFIG"
else
# Default values
MIN_PASSWORD_LENGTH=8
MAX_PASSWORD_AGE=90
PASSWORD_HISTORY=5
MAX_FAILED_ATTEMPTS=5
LOCK_TIMEOUT=300
COMPLEXITY_REQUIRED=true
fi
}
# Check password compliance for all users
check_password_compliance() {
log_action "Starting password compliance check"
local compliance_data='{"timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","users":[]}'
local non_compliant_count=0
# Get all local users
local users=$(dscl . list /Users | grep -v '^_' | grep -v 'daemon\|nobody\|root')
while IFS= read -r username; do
if [[ -n "$username" ]]; then
log_action "Checking compliance for user: $username"
local user_data='{"username":"'$username'","compliant":true,"issues":[]}'
local issues=()
# Check password age
local last_change=$(dscl . read "/Users/$username" passwordPolicyOptions | grep -o 'passwordLastSetTime</key><real>[0-9.]*' | cut -d'>' -f2 || echo "0")
if [[ -n "$last_change" && "$last_change" != "0" ]]; then
local age_days=$(( ($(date +%s) - ${last_change%.*}) / 86400 ))
if [[ $age_days -gt $MAX_PASSWORD_AGE ]]; then
issues+=("Password expired ($age_days days old)")
fi
fi
# Check account lockout status
local failed_attempts=$(dscl . read "/Users/$username" | grep -c "authenticationHint" || echo "0")
# Check secure token status
if ! sysadminctl -secureTokenStatus "$username" 2>&1 | grep -q "ENABLED"; then
issues+=("No SecureToken")
fi
# Update compliance data
if [[ ${#issues[@]} -gt 0 ]]; then
user_data='{"username":"'$username'","compliant":false,"issues":["'$(IFS='","'; echo "${issues[*]}")'"]}'
((non_compliant_count++))
fi
# Add to compliance report
compliance_data=$(echo "$compliance_data" | jq --argjson user "$user_data" '.users += [$user]')
fi
done <<< "$users"
# Save compliance report
echo "$compliance_data" | jq . > "$COMPLIANCE_REPORT"
log_action "Compliance check completed: $non_compliant_count non-compliant users found"
if [[ $non_compliant_count -gt 0 ]]; then
log_action "⚠️ Password compliance issues detected"
return 1
else
log_action "✅ All users are password compliant"
return 0
fi
}
# Enforce password policies
enforce_password_policies() {
log_action "Starting password policy enforcement"
# Configure system-wide password policies
log_action "Applying system-wide password policies"
# Set password complexity requirements
if [[ "$COMPLEXITY_REQUIRED" == "true" ]]; then
sudo pwpolicy -a diradmin -setglobalpolicy "minChars=$MIN_PASSWORD_LENGTH requiresAlpha requiresNumeric"
log_action "Password complexity requirements set"
fi
# Configure account lockout
sudo pwpolicy -a diradmin -setglobalpolicy "maxFailedLoginAttempts=$MAX_FAILED_ATTEMPTS"
log_action "Account lockout policy set to $MAX_FAILED_ATTEMPTS failed attempts"
# Configure password history
sudo pwpolicy -a diradmin -setglobalpolicy "usingHistory=$PASSWORD_HISTORY"
log_action "Password history set to $PASSWORD_HISTORY previous passwords"
# Configure screen lock
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
log_action "Screen lock password requirement enabled"
# Set automatic screen lock
defaults -currentHost write com.apple.screensaver idleTime -int "$LOCK_TIMEOUT"
log_action "Automatic screen lock set to $LOCK_TIMEOUT seconds"
}
# Generate password compliance report
generate_compliance_report() {
log_action "Generating password compliance report"
if [[ -f "$COMPLIANCE_REPORT" ]]; then
local total_users=$(jq '.users | length' "$COMPLIANCE_REPORT")
local compliant_users=$(jq '.users | map(select(.compliant == true)) | length' "$COMPLIANCE_REPORT")
local non_compliant_users=$(jq '.users | map(select(.compliant == false)) | length' "$COMPLIANCE_REPORT")
echo "=== Password Compliance Report ==="
echo "Report Generated: $(jq -r '.timestamp' "$COMPLIANCE_REPORT")"
echo "Total Users: $total_users"
echo "Compliant Users: $compliant_users"
echo "Non-Compliant Users: $non_compliant_users"
echo "Compliance Rate: $(( (compliant_users * 100) / total_users ))%"
if [[ $non_compliant_users -gt 0 ]]; then
echo ""
echo "Non-Compliant Users:"
jq -r '.users[] | select(.compliant == false) | "- " + .username + ": " + (.issues | join(", "))' "$COMPLIANCE_REPORT"
fi
else
echo "No compliance report found. Run compliance check first."
fi
}
# Automated password security tasks
run_security_maintenance() {
log_action "=== Starting automated password security maintenance ==="
# Load configuration
load_policy_config
# Check compliance
check_password_compliance
# Enforce policies
enforce_password_policies
# Generate report
generate_compliance_report
log_action "=== Password security maintenance completed ==="
}
# Main execution
main() {
local action="${1:-maintenance}"
case "$action" in
"compliance")
load_policy_config
check_password_compliance
;;
"enforce")
load_policy_config
enforce_password_policies
;;
"report")
generate_compliance_report
;;
"maintenance")
run_security_maintenance
;;
*)
echo "Usage: $0 [compliance|enforce|report|maintenance]"
echo " compliance - Check password compliance for all users"
echo " enforce - Apply password policies"
echo " report - Generate compliance report"
echo " maintenance - Run full maintenance cycle (default)"
exit 1
;;
esac
}
# Execute main function
main "$@"
Password Policy Configuration File
Create a configuration file for password policies:
#!/bin/bash
# Create password policy configuration
create_policy_config() {
local config_dir="/etc/macfleet"
local config_file="$config_dir/password_policy.conf"
# Create directory if it doesn't exist
sudo mkdir -p "$config_dir"
# Create configuration file
sudo tee "$config_file" > /dev/null << 'EOF'
# MacFleet Password Policy Configuration
# Password Requirements
MIN_PASSWORD_LENGTH=8
MAX_PASSWORD_LENGTH=128
REQUIRE_UPPERCASE=true
REQUIRE_LOWERCASE=true
REQUIRE_NUMBERS=true
REQUIRE_SPECIAL_CHARS=true
# Password Rotation
MAX_PASSWORD_AGE=90 # Days before password expires
PASSWORD_HISTORY=5 # Number of previous passwords to remember
EXPIRATION_WARNING_DAYS=14 # Days before expiration to warn user
# Account Security
MAX_FAILED_ATTEMPTS=5 # Failed login attempts before lockout
LOCKOUT_DURATION=1800 # Account lockout duration in seconds
AUTO_UNLOCK=true # Automatically unlock after lockout duration
# Screen Security
LOCK_TIMEOUT=300 # Screen lock timeout in seconds
IMMEDIATE_LOCK=true # Require password immediately after lock
SCREEN_SAVER_TIMEOUT=600 # Screen saver activation timeout
# Compliance
COMPLEXITY_REQUIRED=true # Enforce password complexity
SECURE_TOKEN_REQUIRED=true # Require SecureToken for all users
REGULAR_AUDITS=true # Enable regular compliance audits
AUDIT_FREQUENCY=7 # Days between compliance audits
# Logging
ENABLE_LOGGING=true # Enable security event logging
LOG_LEVEL="INFO" # Log level: DEBUG, INFO, WARN, ERROR
LOG_RETENTION=30 # Days to retain log files
EOF
echo "Password policy configuration created at: $config_file"
}
create_policy_config
Integration with MacFleet Management
#!/bin/bash
# MacFleet password management integration
macfleet_password_integration() {
echo "=== MacFleet Password Management Integration ==="
# Device registration
local device_id=$(system_profiler SPHardwareDataType | grep "Hardware UUID" | awk '{print $3}')
local hostname=$(hostname)
echo "Device ID: $device_id"
echo "Hostname: $hostname"
# Report to MacFleet API (placeholder)
local api_endpoint="https://api.macfleet.com/devices/$device_id/security"
local report_data='{
"device_id": "'$device_id'",
"hostname": "'$hostname'",
"timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",
"password_policy_status": "enforced",
"compliance_check": "'$(date +%s)'",
"security_level": "enterprise"
}'
echo "Security status reported to MacFleet"
}
macfleet_password_integration
Important Security Notes
Password Storage and Handling
- Never log actual passwords in scripts or logs
- Use secure credential management for administrative passwords
- Implement proper encryption for any stored authentication data
- Regular security audits of password policies and compliance
Best Practices
- Test policies on development devices before fleet deployment
- Gradual rollout of new password requirements
- User communication about policy changes
- Emergency procedures for account lockouts and password resets
Monitoring and Compliance
- Regular audits of password compliance across the fleet
- Automated alerts for policy violations
- Reporting dashboard for security status
- Integration with enterprise identity management systems
This enterprise password enforcement system provides comprehensive security management for MacFleet devices while maintaining usability and compliance with enterprise security standards.