User Management Automation : Bash Script Guide
Tags: devops, linux, sysops, tutorial
Published: 2024-07-01 18:46:28

Trying to manage user accounts in a Linux environment can be a stressful, time-consuming and error-prone process, especially in a large organization with many users. Automating this process not only makes things easy, efficient and time-saving, but also ensures consistency and accuracy. In this article, we'll look at a Bash script designed to automate user creation, group assignment and password management. This script reads from a file containing user information, creates users and groups as specified, sets up home directories with appropriate permissions, generates random passwords and logs all actions. 

## Script Overview
Here's a breakdown of the bash script used to automate the user management process:

```sh
#!/bin/bash

# Constants for the script
SECURE_FOLDER="/var/secure"  # The path to the secure folder where user information will be stored
LOG_FILE="/var/log/user_management.log"  # The path to the log file for recording script execution
PASSWORD_FILE="/var/secure/user_passwords.csv"  # The path to the file where user passwords will be stored

log_message() {
    # Function to log a message with a timestamp to the log file
    # Arguments:
    #   $1: The message to be logged
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# Function to generate a random password
generate_password() {
    tr -dc 'A-Za-z0-9!@#$%^&*()-_' < /dev/urandom | head -c 16
}

if [ ! -d "$SECURE_FOLDER" ]; then
    # Check if the secure folder exists, if not, create it
    mkdir -p $SECURE_FOLDER
    log_message "Secure folder created."
fi

# Check for command-line argument
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <path_to_user_file>"
    exit 1
fi

USER_FILE="$1"

# Check if file exists
if [ ! -f "$USER_FILE" ]; then
    echo "File not found: $USER_FILE"
    exit 1
fi

# Create the log file and password file if they do not exist
touch $LOG_FILE
touch $PASSWORD_FILE

# Set the permissions on the password file to be read/write only by the user executing the script
chmod 600 $PASSWORD_FILE

# Write the header to the password file if it is empty
if [ ! -s $PASSWORD_FILE ]; then
    echo "Username,Password" > $PASSWORD_FILE
fi

# Add new line to USER_FILE to avoid error in while loop
echo "" >> $USER_FILE

# read one by one, there is no seperator so it will read line by line
while read -r line; do
    # Trim whitespace, and seperate them via ;
    username=$(echo "$line" | xargs | cut -d';' -f1)
    groups=$(echo "$line" | xargs | cut -d';' -f2)

    # Skip empty lines
    if [ -z "$username" ]; then
        continue
    fi
    
    # Create user group (personal group)
    if ! getent group "$username" > /dev/null; then
        groupadd "$username"
        log_message "Group '$username' created."
    else
        log_message "Group '$username' already exists."
    fi
    
    # Create user if not exists
    if ! id -u "$username" > /dev/null 2>&1; then
        useradd -m -g "$username" -s /bin/bash "$username"
        log_message "User '$username' created with home directory."
        
        # Generate and set password
        password=$(generate_password)
        echo "$username:$password" | chpasswd
        echo "$username,$password" >> $PASSWORD_FILE
        log_message "Password set for user '$username'."
        
        # Set permissions for home directory
        chmod 700 "/home/$username"
        chown "$username:$username" "/home/$username"
        log_message "Home directory permissions set for user '$username'."
    else
        log_message "User '$username' already exists."
    fi
        
    # Add user to additional groups
    IFS=',' read -ra group_array <<< "$groups"
        for group in "${group_array[@]}"; do
            group=$(echo "$group" | xargs) # Trim whitespace
            if [ -n "$group" ]; then
                if ! getent group "$group" > /dev/null; then
                    groupadd "$group"
                    log_message "Group '$group' created."
                fi
                usermod -aG "$group" "$username"
                log_message "User '$username' added to group '$group'."
            fi
    done
done < "$USER_FILE"
```

## Script Breakdown
Let's break down the key components of this script and understand how they work together to automate user management.

- Setting up directories and files 
The script begins by defining the locations of the secure folder, log file and password file:

```sh
SECURE_FOLDER="/var/secure"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.csv"
```
A function, log_message(), is used to log messages with a timestamp:

```sh
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
```

The script checks if the secure folder exists and creates it if it doesn't:

```sh
if [ ! -d "$SECURE_FOLDER" ]; then
    mkdir -p $SECURE_FOLDER
    log_message "Secure folder created."
fi
```
- Validating Input

The script expects a single argument: the path to the user file. It checks if the argument is provided and if the file exists:

```sh
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <path_to_user_file>"
    exit 1
fi

USER_FILE="$1"

if [ ! -f "$USER_FILE" ]; then
    echo "File not found: $USER_FILE"
    exit 1
fi
```

- Preparing Log and Password Files

The script creates and secures the log and password files:

```sh
touch $LOG_FILE
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE

if [ ! -s $PASSWORD_FILE ]; then
    echo "Username,Password" > $PASSWORD_FILE
fi
```

- Processing the User File

The main part of the script reads the user file line by line, processes each user, and performs the following steps:

- Read Username and Groups: It reads the username and groups from each line, trimming any whitespace:

```sh
while IFS=';' read -r username groups; do
    username=$(echo $username | xargs)
    groups=$(echo $groups | xargs)
    
    if [ -z "$username" ]; then
        continue
    fi
```

- Create User Group: If the user's personal group does not exist, it creates the group:

```sh
if ! getent group "$username" > /dev/null; then
    groupadd "$username"
    log_message "Group '$username' created."
else
    log_message "Group '$username' already exists."
fi
```

- Create User: If the user does not exist, it creates the user with a home directory and assigns the personal group. It also generates a random password, sets it for the user, and secures the home directory:

```sh
if ! id -u "$username" > /dev/null 2>&1; then
    useradd -m -g "$username" -s /bin/bash "$username"
    log_message "User '$username' created with home directory."
    
    password=$(tr -dc 'A-Za-z0-9!@#$%^&*()-_' < /dev/urandom | head -c 16)
    echo "$username:$password" | chpasswd
    echo "$username,$password" >> $PASSWORD_FILE
    log_message "Password set for user '$username'."
    
    chmod 700 "/home/$username"
    chown "$username:$username" "/home/$username"
    log_message "Home directory permissions set for user '$username'."
else
    log_message "User '$username' already exists."
fi
```

- Assign Groups: The script reads the additional groups for the user and assigns them, creating any missing groups:

```sh
IFS=',' read -ra group_array <<< "$groups"
for group in "${group_array[@]}"; do
    group=$(echo $group | xargs)
    if ! getent group "$group" > /dev/null; then
        groupadd "$group"
        log_message "Group '$group' created."
    fi
    usermod -aG "$group" "$username"
    log_message "User '$username' added to group '$group'."
done
```

- Finalize: The script ensures the password file is secure:

```sh
chmod 600 $PASSWORD_FILE
```

The code above only allows the authorized user (executor) to read the contents of the password csv file.

## Conclusion
This script provides a robust solution for managing user accounts in a Linux environment. By automating user creation, group assignment, and password management, it ensures consistency and saves valuable time for system administrators. The use of logging and secure password storage further enhances the reliability and security of the user management process.

For more information about automation and system administration, check out the HNG Internship program at [HNG Internship](https://hng.tech/internship). The program offers a wealth of resources and opportunities for aspiring DevOps engineers. Additionally, you can explore hiring opportunities at [HNG Hire](https://hng.tech/hire) and premium services at [HNG Premium](https://hng.tech/premium).

By implementing such automation scripts, you can streamline your operations, reduce errors, and improve overall system security and efficiency.