DEV Community

Simeon Udoh
Simeon Udoh

Posted on

Automating User and Group Management with Bash Scripting.

In modern IT environments, efficient user and group management is key to maintaining security and operational integrity. Manually creating and managing users across multiple systems is time-consuming and very prone to errors due to its repetitiveness. Automation becomes a handy tool for handling repetitive tasks like creating and managing users, groups and permissions. This article will walk you through a Bash script that automates the processes of user and group creation, and group assignment based on a structured input file. The bash script also contains a logging mechanism for reviewing all operations of the script.

Objective

The script is named create_users.sh. It reads a text file containing usernames and their respective groups, creates users, assigns them to specified groups, generates random passwords securely for each user and stores them. It then logs all actions.

Prerequisites

To successfully follow this tutorial, you need the following:

  • A Linux machine with root privileges: The script requires administrative rights to create users, groups, and manage file permissions (sudo or root access).

  • Basic Knowledge of Bash commands and scripting: Familiarity with navigating the command line and editing scripts will help in understanding and customizing the provided script.

  • A text editor of choice (vi, nano, vim, etc): You'll use a text editor to modify the script and prepare input files. Choose one that you're comfortable with or have experience using.

Overview
The script automates the creation of users and groups by reading input from a text file formatted as username;groups. In a nutshell, the script does the following:

  • Reads a text file passed as an argument to the script at runtime.
  • Validates root privileges and the existence of a secure directory for password storage (/var/secure).
  • Creates usernames and assigns them to their respective groups specified in the input file.
  • Generates strong (16 digit), random passwords for each user and securely stores them in /var/secure/user_passwords.txt.
  • Logs all actions to /var/log/user_management.log for audit purposes.

Writing our script.

Create script file

Open your terminal and create an empty file named create_user.sh.
touch create_user.sh

Using your preferred editor, open the create_user.sh file we just created. For this tutorial, we will be using vim text editor. feel free to use your editor of choice.

vim create_user.sh

Add the shebang line
At the top of the script, add the shebang line.

#!/bin/bash
Enter fullscreen mode Exit fullscreen mode

Check if the script is run with root privileges.
In a linux system, creating users and groups, setting permissions, etc typically involve using administrative privileges. After the shebang line, add the following code.

# Check if running as root
if [[ $(id -u) -ne 0 ]]; then
    echo "This script must be run as root."
    exit 1
fi
Enter fullscreen mode Exit fullscreen mode

The code check above if [[ $(id -u) -ne 0 ]]; then retrieves the user's id then it checks if the retrieved id does not equal to 0. If it does, it means the user running the script has admin privileges and continues to the next phase of the script. It terminates if the user does not have root privileges.

Ensure /var/secure directory exists for storing passwords securely

The "/var/secure" directory is used for typically used as a secure directory where sensitive information, such as user passwords, can be stored with restricted access.


if [[ ! -d "/var/secure" ]]; then
    mkdir -p /var/secure
    chown root:root /var/secure
    chmod 700 /var/secure
fi
Enter fullscreen mode Exit fullscreen mode

If the "/var/secure" directory does not exist, it is immediately created with all permissions (read, write, execute) set for the user.

Setting Up Our Variables

Before proceeding, we need to set up some variables that would be reused in other parts of the script.

# Variables
INPUT_FILE="$1"
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
Enter fullscreen mode Exit fullscreen mode
  • INPUT_FILE variable is set to $1 which is the text file that is passed as an argument to our script.
  • LOG_FILE variable is to the user_management.log in /var/log/ and used for storing logs from our script.

  • PASSWORD_FILE variable is set to the user_passwords.txt file in /var/secure/ directory which was created earlier by our script after initial checks if the directory doesn't exist.

Creating The Generate Password Utility Function

The script contains a utility function that act as a helper function for performing the task of generating a secure password which we would use in the core part of the script.

generate_password

This helper function helps to generate a strong a strong random password using the /dev/urandom linux kernel interface for generating random passwords.

generate_password() {
    tr -dc 'A-Za-z0-9!@#$%^&*()_+=-[]{}|;:<>,.?/~' </dev/urandom | head -c 16
}
Enter fullscreen mode Exit fullscreen mode

The above code generates a 16-digit random password using the Kernel's built-in random number generator. The generated password consists of uppercase letters (A-Z), lowercase letters (a-z), digits (0-9), and some special characters.

User and Group Creation:

This is the core part of the script. It reads each line from the input file ($1) to create users and assign them to specified groups and logs all action to the

while IFS=";" read -r user groups; do
    # Remove whitespaces from user and groups
    user=$(echo "$user" | xargs)
    groups=$(echo "$groups" | xargs)

    # Validate username before creating user
    if [[ -z "$user" ]]; then
        echo "Invalid username. Skipping user creation."
        continue
    fi

    # Check if user already exists
    if id "$user" >/dev/null 2>&1; then
        echo "User $user already exists. Skipping user creation."
        continue
    fi

    # Create a personal group for the user
    groupadd "$user" 2>/dev/null
    usermod -aG "$user" "$user"

    # Add user to specified groups
    IFS=',' read -ra group_list <<< "$groups"
    for group in "${group_list[@]}"; do
        group=$(echo "$group" | xargs)
        if [ -n "$group" ]; then
            groupadd "$group" 2>/dev/null
            usermod -aG "$group" "$user"
        fi
    done

    # Generate and store password securely
    password=$(generate_password)
    echo "$user:$password" >> "$PASSWORD_FILE"

    # Log actions
    echo "$(date +'%Y-%m-%d %H:%M:%S') Created user '$user' and added to groups: $groups" >> "$LOG_FILE"

done < "$INPUT_FILE"
Enter fullscreen mode Exit fullscreen mode

Detailed breakdown of the above code blocks:

  • Read in the file
    Firstly, we begin a while loop which is used to read in the file and set our IFS (Internal Field Seperator) to the semi-colon ";".
    while IFS=";" read -r user groups; do. The content of the text file is read in and it is then separated by ";" to denote which part of the content are user names and group names.

  • Trim whitespaces
    Next, we trim all whitespaces around the user names and group names using the xargs command-line utility.

 user=$(echo "$user" | xargs)
 groups=$(echo "$groups" | xargs)
Enter fullscreen mode Exit fullscreen mode
  • Validate users

We validate user names using two criteria

  1. The user name is not empty: if [[ -z "$user" ]];
  2. The user name does not already exist: if id "$user" >/dev/null 2>&1; then

if the user name is empty or exists, it is skipped and the script continues.

  • Create user own groups We then create a group specifically for the user and adds the user to their groups.
groupadd "$user" 2>/dev/null
usermod -aG "$user" "$user"
Enter fullscreen mode Exit fullscreen mode
  • Add user to specified groups Here, we read in the text file again passed as an argument to the script but this time, the IFS is set to ','. This way, we can get the group names even if the user belongs to more than one specified groups.
IFS=',' read -ra group_list <<< "$groups"
    for group in "${group_list[@]}"; do
        group=$(echo "$group" | xargs)
        if [ -n "$group" ]; then
            groupadd "$group" 2>/dev/null
            usermod -aG "$group" "$user"
        fi
    done
Enter fullscreen mode Exit fullscreen mode
  • Generate and Store passwords for each user

Recall that we earlier created a generate_password helper function for our script and we can now use it to generate and store each user's password to the $PASSWORD_FILE.

password=$(generate_password)
echo "$user:$password" >> "$PASSWORD_FILE"
Enter fullscreen mode Exit fullscreen mode
  • Log actions After all operations, we add a new log entry to our log file for each user operation.
echo "$(date +'%Y-%m-%d %H:%M:%S') Created user '$user' and added to groups: $groups" >> "$LOG_FILE"
Enter fullscreen mode Exit fullscreen mode
  • End the Loop done < "$INPUT_FILE"

Run Our Script

set execute permission for the create_user.sh file.

   chmod +x create_user.sh
Enter fullscreen mode Exit fullscreen mode

Here is an sample user input file you can use for testing our bash script: vim user_groups.txt and paste the below text:

nelson;cloudeng,sre
victor;backend
john;qa
jane;dev,manager
robert;marketing
emily;design,research
michael;devops
olivia;design,research
william;support
sophia;content,marketing
daniel;devops,sre
ava;dev,qa
Enter fullscreen mode Exit fullscreen mode

now run the script using:

./create_users.sh user_groups.txt
Enter fullscreen mode Exit fullscreen mode

Checking Our Script Logs:

cat /var/log/user_management.log
Enter fullscreen mode Exit fullscreen mode

Conclusion

Thanks for following me on this tutorial. This technical article was created as part of my Stage 1 task for HNG Internship.

HNG is an internship that helps people hone and improve their tech skills. To learn more, visit the HNG Internship website: https://hng.tech/internship

Top comments (0)