Automating User Management with Advanced Bashscript
Tags: bash, advancedbashscripting, createusersinlinux, automation
Published: 2024-07-02 21:49:10

As part of the requirements of my DevOps internship with [HNG](https://hng.tech/internship), I am required to create a bash script to automate user management.
Managing users in a Linux environment can be a repetitive and error-prone task if done manually, especially when dealing with a large number of users. To simplify this process, you can use a bash script to automate user creation, group assignment, and password management. Let's walk through a comprehensive bash script designed to streamline user management. This script reads a list of usernames and groups from a text file, creates users and groups accordingly, sets up home directories, generates random passwords, and logs all actions for audit purposes. You can find the complete script on my [GitHub repository](https://github.com/laraadeboye/user-creation-script).

This bash script performs several key tasks:

1. **Ensures root privileges**: The script checks if it is run as root.
2. **Logs actions**: Logs important actions and errors for audit and debugging.
3. **Validates inputs**: Ensures usernames and group names are valid.
4. **Creates users and groups**: Adds new users and groups as specified in an input file.
5. **Sets passwords**: Generates and sets random passwords for new users.
6. **Configures home directories**: Sets appropriate permissions for user home directories.



### Detailed Explanation of script.

- **Script Header and Logging**
The script begins by defining a logging function to record actions and errors to a log file.

```bash
#!/usr/bin/bash

log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
```


- **Password Generation**
A function to generate random passwords is defined, which uses /dev/urandom for secure random number generation.

```bash
generate_password() {
    local password_length=12
    tr -dc A-Za-z0-9 </dev/urandom | head -c $password_length
}
```


- **Ensuring Root Privileges**
The script checks if it is run with root privileges. If not, it logs an error and exits. Root users have user id 0.

```bash
if [ "$(id -u)" -ne 0 ]; then
    echo "This script must be run as root or with sudo privileges" >&2
    log "Script not run as root or with sudo privileges"
    exit 1
fi
```

- **File Paths and Initial Checks**
The script sets file paths for the user input file, log file, and password storage. It also verifies the existence of these files.

```bash
USER_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

if [ -z "$USER_FILE" ]; then
    echo "Usage: $0 <name-of-text-file>"
    log "No user file provided. Usage: $0 <name-of-text-file>"
    exit 1
fi

if [ ! -f "$USER_FILE" ]; then
    echo "Input file not found"
    log "Input file '$USER_FILE' not found"
    exit 1
fi

if [ ! -f "$LOG_FILE" ]; then
    touch "$LOG_FILE"
    chmod 0600 "$LOG_FILE"
    log "Log file created: $LOG_FILE"
fi

if [ ! -f "$PASSWORD_FILE" ]; then
    mkdir -p /var/secure
    touch "$PASSWORD_FILE"
    chmod 0600 "$PASSWORD_FILE"
    log "Password file created: $PASSWORD_FILE"
fi
```
- **Input Validation**
The script validates the usernames and group names using regular expressions to ensure they contain only alphanumeric characters, hyphens, and underscores.

```bash
validate_username() {
    if [[ ! "$1" =~ ^[a-zA-Z0-9_-]+$ ]]; then
        return 1
    fi
    return 0
}

validate_groups() {
    IFS=',' read -ra group_list <<< "$1"
    for group in "${group_list[@]}"; do
        if [[ ! "$group" =~ ^[a-zA-Z0-9_-]+$ ]]; then
            return 1
        fi
    done
    return 0
}

```

- **User and Group Creation**
The script reads the user file line by line, creating users and their groups as necessary. It also ensures that each user has a personal group and sets up the home directory with appropriate permissions.

```bash
while IFS=';' read -r username groups; do
    username=$(echo "$username" | xargs)
    groups=$(echo "$groups" | xargs)

    if [ -z "$username" ] || [ -z "$groups" ]; then
        log "Invalid line format in user file: '$username;$groups'"
        user_creation_failed=true
        continue
    fi

    if ! validate_username "$username"; then
        log "Invalid username format: '$username'"
        user_creation_failed=true
        continue
    fi

    if ! validate_groups "$groups"; then
        log "Invalid group format: '$groups'"
        group_creation_failed=true
        continue
    fi

    if id "$username" &>/dev/null; then
        log "User $username already exists."
        continue
    fi

    all_users_exist=false

    if ! getent group "$username" > /dev/null; then
        if groupadd "$username"; then
            log "Group $username created."
        else
            log "Failed to create group $username."
            group_creation_failed=true
            continue
        fi
    fi

    IFS=',' read -ra group_list <<< "$groups"
    for group in "${group_list[@]}"; do
        if ! getent group "$group" > /dev/null; then
            if groupadd "$group"; then
                log "Group $group created."
            else
                log "Failed to create group $group."
                group_creation_failed=true
            fi
        fi
    done
    unset IFS

    if useradd -m -g "$username" -G "$groups" "$username"; then
        log "User $username created and added to groups $groups"
        users_created=true
        any_users_created=true
    else
        log "Failed to create user $username"
        user_creation_failed=true
        continue
    fi

    password=$(generate_password)
    log "Generated password for $username"

    if echo "$username:$password" | chpasswd; then
        echo "$username,$password" >> "$PASSWORD_FILE"
        log "Password set for $username and stored securely"
    else
        log "Failed to set password for $username"
        password_setting_failed=true
        continue
    fi

    if chown "$username:$username" "/home/$username" && chmod 700 "/home/$username"; then
        log "Home directory for $username set up with appropriate permissions."
    else
        log "Failed to set up home directory for $username"
        home_directory_setup_failed=true
    fi

done < "$USER_FILE"
```

- **Summary and Exit**
After processing all lines, the script logs a summary of the actions taken and exits.

```bash
log "User creation script run completed."

if [ "$any_users_created" = true ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - User creation script completed successfully."
elif [ "$all_users_exist" = true ]; then
    echo "Users already exist. Nothing left to do"
else
    echo "$(date '+%Y-%m-%d %H:%M:%S') - No users were created successfully. Check log file."
    log "No users were created successfully. Please check the input file format: username;group1,group2,group3."
fi

[ "$user_creation_failed" = true ] && echo "Users creation incomplete." && log "Some users were not created due to errors. Check file format"
[ "$password_setting_failed" = true ] && echo "Users' passwords creation incomplete." && log "Some users' passwords were not set due to errors. Check file format"
[ "$group_creation_failed" = true ] && echo "Groups creation incomplete." && log "Some groups were not created due to errors. Check file format"
[ "$home_directory_setup_failed" = true ] && echo "Home directories creation incomplete." && log "Some home directories were not set up due to errors."

exit 0

```

**Conclusion**
This script offers a reliable way to automate processes related to user management, lowering the possibility of mistakes and saving important administrative time. System administrators can create user accounts in a consistent and safe manner with this script, which also manages passwords and group assignments. Detailed logs are kept for accountability and debugging purposes. To get real-time internship experience, sign up with [HNG](https://hng.tech/premium)