Automating User and Group Management with a Bash Script
Published: 2024-07-02 11:07:21

## Automating User and Group Management with a Bash Script
inspired by  [HNG ](https://hng.tech/internship).

As a SysOps engineer, one of your routine tasks involves managing users and groups on a server. This can be time-consuming and prone to errors, especially when dealing with many users. Automation is the key to efficiency and reliability. This article will walk you through a Bash script that automates creating users and groups, setting up home directories with appropriate permissions, generating random passwords, and logging all actions.

This project was inspired by HNG internship 11, DevOps trcak of stage one.
visit [HNG WEBSITE](https://hng.tech/premium) to learn more about the program

### Overview

1. Creates users and their groups.
2. Adds users to additional specified groups.
3. Sets up home directories with correct permissions and ownership.
4. Generates random passwords for users.
5. Logs all actions to /var/log/user_management.log.
Stores generated passwords securely in /var/secure/user_passwords.txt

## A bash script create_users.sh will be created:

The script, create_users.sh, reads a text file containing usernames and their associated groups. Each line in the file is formatted as user;groups, where groups are delimited by commas. The script performs the following tasks:

**Example Input File**
```
light;sudo,dev,www-data
idimma;sudo
mayowa;dev,www-data

```
**The script**
Below is the complete script

```
#!/bin/bash

# Define log and password files
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

# Create log and password files if they don't exist
touch $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE

# Function to log messages
log_message() {
    echo "$(date +'%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}

# Function to generate random password
generate_password() {
    tr -dc A-Za-z0-9 </dev/urandom | head -c 12 ; echo ''
}

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

# Read the input file
INPUT_FILE=$1

# Check if the input file exists
if [ ! -f $INPUT_FILE ]; then
    echo "Input file not found!"
    exit 1
fi

while IFS=';' read -r username groups; do
    # Remove leading and trailing whitespaces
    username=$(echo $username | xargs)
    groups=$(echo $groups | xargs)

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

    # Create a personal group for the user
    groupadd $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create group $username."
        continue
    fi
    log_message "Group $username created successfully."

    # Create user and add to personal group
    useradd -m -g $username -s /bin/bash $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create user $username."
        continue
    fi
    log_message "User $username created successfully."

    # Create additional groups if they don't exist and add user to groups
    IFS=',' read -ra group_array <<< "$groups"
    for group in "${group_array[@]}"; do
        group=$(echo $group | xargs)
        if [ -z "$group" ]; then
            continue
        fi
        if ! getent group $group >/dev/null; then
            groupadd $group
            if [ $? -ne 0 ]; then
                log_message "Failed to create group $group."
                continue
            fi
            log_message "Group $group created successfully."
        fi
        usermod -aG $group $username
        log_message "User $username added to group $group."
    done

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

    # Generate random password and store it
    password=$(generate_password)
    echo "$username:$password" | chpasswd
    echo "$username:$password" >> $PASSWORD_FILE
    log_message "Password set for user $username."

done < "$INPUT_FILE"

log_message "User and group creation process completed."

exit 0


```
**Detailed Explanation**

Let's break down the script line by line to understand how it works.

**1. Shebang and Definition**s

```
#!/bin/bash
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"

```
The shebang (#!/bin/bash) indicates that the script should be executed using the Bash shell.
LOG_FILE and PASSWORD_FILE specify the paths for the log and password files.
**2. Creating Log and Password Files**
```
touch $LOG_FILE
mkdir -p /var/secure
touch $PASSWORD_FILE
```
touch $LOG_FILE creates the log file if it doesn't exist.
mkdir -p /var/secure creates the directory /var/secure if it doesn't exist.
touch $PASSWORD_FILE creates the password file if it doesn't exist.

**3. Logging Function**

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

```
'log_message' is a function that logs messages with a timestamp to both the log file and the terminal.

**4. Password Generation Function**
```
generate_password() {
    tr -dc A-Za-z0-9 </dev/urandom | head -c 12 ; echo ''
}
```
This function generates a random 12-character alphanumeric password.
**5. Input File Check**
```
if [ $# -ne 1 ]; then
    echo "Usage: $0 <input_file>"
    exit 1
fi
INPUT_FILE=$1
if [ ! -f $INPUT_FILE ]; then
    echo "Input file not found!"
    exit 1
fi
```
The script checks if exactly one argument (the input file) is provided and if the file exists.
**6. Reading the Input File**
```
while IFS=';' read -r username groups; do
    username=$(echo $username | xargs)
    groups=$(echo $groups | xargs)
```
his loop reads the input file line by line, splitting each line into username and groups using ; as the delimiter.
xargs removes leading and trailing whitespaces.

**7. Checking for Existing Users**
```
    if id "$username" &>/dev/null; then
        log_message "User $username already exists. Skipping..."
        continue
    fi
```
This checks if the user already exists and logs a message if they do, then skips to the next iteration
**8. Creating Personal Group and User**
```
    groupadd $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create group $username."
        continue
    fi
    log_message "Group $username created successfully."
    useradd -m -g $username -s /bin/bash $username
    if [ $? -ne 0 ]; then
        log_message "Failed to create user $username."
        continue
    fi
    log_message "User $username created successfully."
```
groupadd $username creates a personal group for the user.
useradd -m -g $username -s /bin/bash $username creates the user with the specified home directory and shell.
**9. Adding User to Additional Groups**
```
    IFS=',' read -ra group_array <<< "$groups"
    for group in "${group_array[@]}"; do
        group=$(echo $group | xargs)
        if [ -z "$group" ]; then
            continue
        fi
        if ! getent group $group >/dev/null; then
            groupadd $group
            if [ $? -ne 0 ]; then
                log_message "Failed to create group $group."
                continue
            fi
            log_message "Group $group created successfully."
        fi
        usermod -aG $group $username
        log_message "User $username added to group $group."
    done
```
This splits the groups string into an array and iterates over each group, creating the group if it doesn't exist and adding the user to it.
**10. Setting Up Home Directory Permissions**
```
    chmod 700 /home/$username
    chown $username:$username /home/$username
    log_message "Permissions set for home directory of $username."
```
chmod 700 /home/$username sets the permissions so that only the user can access their home directory.
chown $username:$username /home/$username sets the ownership of the home directory.
**11. Generating and Storing Passwords**
```
    password=$(generate_password)
    echo "$username:$password" | chpasswd
    echo "$username:$password" >> $PASSWORD_FILE
    log_message "Password set for user $username."
```
This generates a random password for the user, sets it, and securely stores it
**12. Completing the Process**
```
done < "$INPUT_FILE"
log_message "User and group creation process completed."
exit
```