Automating User and Group Management with Bash: A Step-by-Step Guide
Published: 2024-07-01 10:44:14

How to Automate User Creation and Group Assignment in Linux Using Bash.

Bash is a powerful scripting tool used to automate various tasks on Unix-like operating systems. One common administrative task is managing users and groups. In this article, we will walk you through a Bash script, create_users.sh which automates the process of creating users and groups, setting up home directories, generating passwords, and logging all actions. This script helps simplifies user management, especially when dealing with multiple users.


Prerequisites

- A basic understanding of Bash scripting and Linux.
- Access to a Linux terminal.

---

The _create_users.sh_ script reads a text file containing 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 to `/var/log/user_management.log`. It also stores the generated passwords securely in `/var/secure/user_passwords.txt`.

Below is my script:

```
#!/bin/bash
if [ $# -ne 1 ]; then
    echo "Use: $0 <filename>"
    exit 1
fi
FILENAME=$1
mkdir -p /var/secure
PASSFILE="/var/secure/user_passwords.txt"
touch $PASSFILE
chmod 600 $PASSFILE
mkdir -p /var/log
LOGFILE="/var/log/user_management.log"
touch $LOGFILE
chmod 644 /var/log/user_management.log
echo "User management started at $(date)" > $LOGFILE


while IFS=';' read -r username groups; do
    username=$(echo "$username" | xargs)
    groups=$(echo "$groups" | xargs)
    if [ -z "$username" ]; then
        continue
    fi
    if id -u "$username"; then
        echo "User $username already exists" | tee -a $LOGFILE
    else
        useradd -m -s /bin/bash -U "$username"
        echo "User $username created with personal group $username" | tee -a $LOGFILE
    fi
    IFS=',' read -r -a group_array <<< "$groups"
    for group in "${group_array[@]}"; do
        if ! getent group "$group" >/dev/null 2>&1; then
            groupadd "$group"
            echo "Group $group created" | tee -a $LOGFILE
        fi
        usermod -aG "$group" "$username"
        echo "User $username added to group $group" | tee -a $LOGFILE
    done


    password=$(openssl rand -base64 12)
    echo "$username:$password" | chpasswd
    echo "Password set for user $username" | tee -a $LOGFILE
    echo "$username,$password" >> $PASSFILE
done < "$FILENAME"
echo "User management completed at $(date)" | tee -a $LOGFILE
```
You can divide this script into three sections:

Create directory, files and permission.
Create User, group and assign each user to there group.
Generate Password.

---

**Detailed explanation of the script:**

**START BASH**
- Shebang line that tells the system to run this script using the Bash shell.

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

**NUM. OF ARGUMENT**
- Checks if exactly one argument (the filename) is provided. This is for error handling.
- If the argument is not equal to one, then print Use: `create_users.sh <filename>.` to show you the correct way of running the task.
- `exit 1`:  This line stops running the script because something is wrong.
- If you run the script with `./create_users.sh myfile.txt`, `$1` is `myfile.txt`

```
if [ $# -ne 1 ]; then
    echo "Use: $0 <filename>"
    exit 1
fi
FILENAME=$1
```

**CREATE PASSWORD FILE AND PERMISSIONS**
- Create a directory `/var/secure`
- Sets up the path for the password file `PASSFILE="/var/secure/user_passwords.txt`
- Then create an empty file `touch $PASSFILE`
- Sets permissions for the password file `chmod 600 $PASSFILE` ensuring that only the owner can read and write to the file.

```
mkdir -p /var/secure
PASSFILE="/var/secure/user_passwords.txt"
touch $PASSFILE
chmod 600 $PASSFILE
```

**CREATE LOG FILE AND PERMISSIONS**
- Create a directory `/var/log`
- Sets up the path for the password file `LOGFILE="/var/log/user_management.LOG`
- Then create an empty file `touch $LOGFILE`
- Give read permission to user and others (Everyone needs to be able to access the log), - - while owner will be given read and write permission. `chmod 644 $LOGFILE`
```
mkdir -p /var/log
LOGFILE="/var/log/user_management.log"
touch $LOGFILE
chmod 644 /var/log/user_management.log
```

**STARTING PROCESS**
- Initializes the `$LOGFILE` with a start message, indicating the start time of the user management process.

```
echo "User management started at $(date)" > $LOGFILE

```
**READ FILE**
- Start a loop that reads a line from the `$FILENAME`, splits it into two parts based on `IFS.`
- Assign the first part to username and the remaining parts to groups .
- The `xargs` command is use to remove any leading or trailing whitespace from username or groups.

```
while IFS=';' read -r username groups; do
    username=$(echo "$username" | xargs)
    groups=$(echo "$groups" | xargs)
```
  
- Checks if `$username` is empty and skip to the next line in the file. This is part of error handling.

```
if [ $# -ne 1 ]; then
        continue
    fi
```
    
**USER**
- Check if the user already exist.
- If the user exists, it logs that the user already exists.
- If the user does not exist, it creates the user, with the personal group and log it.

```
if id -u "$username"; then
        echo "User $username already exists" | tee -a $LOGFILE
    else
        useradd -m -s /bin/bash -U "$username"
        echo "User $username created with personal group $username" | tee -a $LOGFILE
    fi
```

**GROUPS**
- Splits the groups string by , into an array called group_array.
- Check if the group in the array already exist in the database.
- If it does not, create a `$group` and log.
- Add `$username` to the group without removing them from other groups and log.

```
for group in "${group_array[@]}"; do
        if ! getent group "$group" >/dev/null 2>&1; then
            groupadd "$group"
            echo "Group $group created" | tee -a $LOGFILE
        fi
        usermod -aG "$group" "$username"
        echo "User $username added to group $group" | tee -a $LOGFILE
    done
```


**PASSWORDS**
- Generate random password for
- Sets the password for `$username` to the value stored in $password
- Print message to show password has been set.
- Then store the user and password to the `$PASSFILE`.
- Ends the loop after processing all lines in the file

```
password=$(openssl rand -base64 12)
    echo "$username:$password" | chpasswd
    echo "Password set for user $username" | tee -a $LOGFILE
    echo "$username,$password" >> $PASSFILE
done < "$FILENAME"
```

**END PROCESS**
'''
- Logs a message indicating the completion of user management, appending it to `$LOGFILE`

```
echo "User management completed at $(date)" | tee -a $LOGFILE
```

---
**Links to HNG Internship**
The HNG Internship is a great opportunity to learn and grow in the field of technology. For more information, visit:
[HNG Internship](https://hng.tech/internship)
[HNG Premium](https://hng.tech/premium)

---
**Running the scripts**

Let's try running the scripts to see if it works.

- Create a file name `test_users.txt`

```
vim test_users.txt

#file content
john;developers,testers
jane;developers
```
- Execute the script `create_users.sh` with the file `test_users.txt`
```
chmod +x create_users.sh
sudo ./create_users.sh test_users.txt
```
- Check the `$LOGFILE`

```
cat /var/log/user_management.log
```
- Switch to root user and check the `$PASSFILE`

```
sudo su
cat /var/secure/user_passwords.txt
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yqxz0k3g8r079s3d729r.png)