Automating User and Group Management with a Bash Script in Linux
Published: 2024-07-01 14:57:30

**Introduction**

Managing users and groups on a Linux system can be a repetitive and error-prone task, especially in environments with frequent onboarding of new developers. To streamline this process, we've developed a bash script called create_users.sh. This script reads a text file containing employee usernames and group names, creates the users and groups as specified, sets up home directories with appropriate permissions, generates random passwords for the users, and logs all actions. Additionally, it stores the generated passwords securely. This article explains the functionality and usage of the create_users.sh script in detail.

**Script Overview**

The create_users.sh script automates the following tasks:
1.	Reads user and group information from a specified text file.
2.	Creates users and groups if they do not already exist.
3.	Sets up home directories with appropriate permissions and ownership.
4.	Generates random passwords for new users.
5.	Logs all actions to /var/log/user_management.log.
6.	Stores generated passwords securely in /var/secure/user_passwords.txt.

**Prerequisites**
•	The script must be run with root privileges.
•	Ensure the target text file containing user information exists.

**Script Structure**
Here's the complete create_users.sh script:

```
#!/bin/bash

# Script to create users and groups, set up home directories, generate passwords,
# and log actions.

# Log file path
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
ENCRYPTION_KEY="/var/secure/encryption_key.txt"

# Function to log messages
log_message() {
    local message=$1
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> $LOG_FILE
}

# Function to generate a random password
generate_password() {
    local password_length=12
    tr -dc A-Za-z0-9 </dev/urandom | head -c $password_length
}

# Ensure the secure directory exists
if [ ! -d /var/secure ]; then
    mkdir -p /var/secure
    chmod 700 /var/secure
    log_message "Created /var/secure directory with 700 permissions."
fi

# Ensure the log file and encryption key exist
touch $LOG_FILE
touch $PASSWORD_FILE
chmod 600 $PASSWORD_FILE

# Generate encryption key if it doesn't exist
if [ ! -f "$ENCRYPTION_KEY" ]; then
    openssl rand -base64 32 > $ENCRYPTION_KEY
    chmod 600 $ENCRYPTION_KEY
    log_message "Generated encryption key."
fi

# Function to encrypt password
encrypt_password() {
    local password=$1
    local encrypted_password=$(echo -n "$password" | openssl enc -aes-256-cbc -base64 -pass file:$ENCRYPTION_KEY)
    echo $encrypted_password
}

# Check if input file is provided
if [ -z "$1" ]; then
    echo "Usage: $0 <user_file>"
    exit 1
fi

USER_FILE="$1"

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

# Read the user file line by line
while IFS=';' read -r username groups; do
    # Skip empty lines or lines without proper format
    if [ -z "$username" ] || [ -z "$groups" ]; then
        log_message "Skipped invalid line: username='$username', groups='$groups'"
        continue
    fi

    # Check if the user already exists
    if id -u "$username" >/dev/null 2>&1; then
        log_message "User $username already exists."
        continue
    fi

    # Create user-specific group if it doesn't exist
    if ! getent group "$username" >/dev/null 2>&1; then
        groupadd "$username"
        log_message "Created group $username."
    fi

    # Create the user with the user-specific group
    useradd -m -g "$username" -s /bin/bash "$username"
    if [ $? -eq 0 ]; then
        log_message "Created user $username with personal group $username."
    else
        log_message "Failed to create user $username."
        continue
    fi

    # Add user to the specified groups
    IFS=',' read -ra group_array <<< "$groups"
    for group in "${group_array[@]}"; do
        if ! getent group "$group" >/dev/null 2>&1; then
            groupadd "$group"
            log_message "Created group $group."
        fi
        usermod -aG "$group" "$username"
        log_message "Added user $username to group $group."
    done

    # Set up home directory permissions
    chmod 700 /home/"$username"
    chown "$username":"$username" /home/"$username"
    log_message "Set permissions for home directory of $username."

    # Generate a random password
    password=$(generate_password)
    echo "$username:$password" | chpasswd
    log_message "Set password for user $username."

    # Encrypt and store the password securely
    encrypted_password=$(encrypt_password "$password")
    echo "$username:$encrypted_password" >> $PASSWORD_FILE
done < "$USER_FILE"

log_message "User creation script completed."

echo "Script execution completed. Check $LOG_FILE for details."

```

**Detailed Explanation**

**Log and Password File Setup**

The script initializes the log file _(/var/log/user_management.log)_ and the password file (_/var/secure/user_passwords.txt_), ensuring they exist and have secure permissions.

Ensure Secure Directory: Checks if the /var/secure directory exists. If not, it creates the directory and sets its permissions to `700` (owner can read, write, and execute; others have no permissions). It then logs this action.

Log File Path: Defines the paths for the log file and the password file.

Logging Function: Defines a function to log messages with timestamps to the log file. This helps keep track of script activities and errors.

Password Generation Function: Defines a function to generate a random password of a specified length (12 characters). The `tr` command filters out unwanted characters, and `head -c` limits the output to the specified length.

Ensure Log and Password Files: Ensures that the log file and password file exist and sets their permissions to `600` (owner can read and write; others have no permissions).

**User File Verification**

Validate User File: Checks if the specified user file exists. If not, it displays an error message and exits. The script verifies that a user file is provided as an argument and that the file exists.

**User and Group Creation Function**

The create_user_and_groups function handles the creation of users and groups. It reads the username and groups, creates any missing groups, and then creates the user if they do not already exist.

Create Groups: Splits the `groups` string by commas into an array and iterates over it. For each group, it checks if the group exists. If not, it creates the group and logs this action.

Create User: Creates the user with the specified groups and sets the shell to `/bin/bash`. The `-m` option creates a home directory for the user. It logs the action or any failure.

Set Home Directory Permissions: Sets the permissions of the user's home directory to `700` (only the user can read, write, and execute) and changes the ownership to the user. Logs this action.
Generate and Set Password: Generates a random password, sets it for the user, and logs this action.
Store Password Securely: Appends the username and password to the password file
Completion Message: Logs the completion of the script and outputs a message indicating the script has finished.

**Usage Example**
To use the script, prepare a user file (e.g., users.txt) with the following format:
```
tosyeno;developers,hngintern,admin
olanifemi;developers,admin
olusam;admin,hngintern
```

Run the script with the path to your user file as an argument:
```
sudo ./create_users.sh users.txt
```

Verifying Group Creation

To verify that the groups have been created, use the getent group groupname command:

getent group developers
getent group hngintern
getent group admin

If the groups exist, these commands will output the group information.

**Conclusion**

The create_users.sh script provides a robust solution for automating user and group management tasks on a Linux system. By automating these tasks, you can ensure consistency, save time, and reduce the risk of manual errors. This script is especially useful in environments with frequent onboarding of new developers, ensuring that all necessary steps are handled efficiently and securely.

HNG internship made this possible and you can reach them on either https://hng.tech/internship or https://hng.tech/premium to be part of the internship program. You can be sure of value for your invested time.

Thank you