Automating user and group management with Bash
Published: 2024-07-05 16:18:32


### Introduction

As a SysOps engineer, managing users and groups on a server is one of your routine tasks. This process can be quite time-consuming and susceptible to errors, particularly when handling numerous users. Automating these tasks is crucial for achieving efficiency and reliability. This article will guide you through a Bash script that automates the creation of users and groups, sets up home directories with correct permissions, generates random passwords, and logs all actions.

### Bash

Bash which stands for "Bourne Again Shell" is a command language interpreter and scripting language commonly used in Unix-like operating systems, such as linux and macOS. It's the default shell for most linux distributions and is widely used for automation tasks, managing system operations, and write scrips.


#### What is Bash script?

A Bash script is a file typically ending with the extension .sh that contain a logical series of related commands to be executed

This project was inspired by HNG internship 11 https://hng.tech/hire, DevOps track of stage one.
visit  https://hng.tech/internship to learn more about the program


### Prerequisite

Before we start, ensure you have:

- Access to a linux server with root privileges
- Basic knowledge of Bash scripting

### Script Overview

The script we'll create will:

1. Create users and groups
2. set up home directories with the correct permissions
3. Generate random passwords for users
4. Log all actions to a specified log file


### User Management Automation project

Let's dive into an extensive project that will show us a step by step guide on how to create user and group management with Bash script.

Here is a step by step guide on how to create user and groups management:

## Creating the script file

First and foremost, Create a new Bash script file 

```
touch create_user.sh
```

Open the file in your preferred text editor:

```
vim create_user.sh
```
Create an employee file where users and group would be located

```
touch employeefile.txt
```
edit your user_data.txt file with a text editor and enter the following user and group below:

```
vim employeefile.txt
```
### Example Input File
light; sudo,dev, www-data
idimma;sudo
mayowa;dev,www-data

**Insert the following script below into your 'create_users.sh' file**

### The 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

```
**Make the script executable**

```
chmod +x create_user.sh
```
**Execute the script**

```
sudo bash ./create_users.sh employeefile.txt
```

## Defining the Script

Start by defining the script header and setting some initial variables:
 **Define Log and Password Files**

```
#!/bin/bash

# Define log and password files
LOG_FILE="/var/log/user_management.log"
PASSWORD_FILE="/var/secure/user_passwords.txt"
```
These lines set the paths for the log file and the file where passwords will be stored.

**Create Log and Password Files if They Don't Exist**

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

```
- touch $LOG_FILE creates the log file if it doesn't already 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.

**Function to Log Messages**

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

```
This function logs messages with a timestamp. tee -a $LOG_FILE appends the log message to the log file while also displaying it on the console.

 **Function to Generate Random Password**

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

```
This function generates a random 12-character password using characters from A-Z, a-z, and 0-9.

 **Check if the Input File is Provided**

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

```
This part ensures that the script is called with exactly one argument (the input file). If not, it displays a usage message and exits.

 **Read the Input File**

```
# Read the input file
INPUT_FILE=$1

```
This assigns the first argument (input file) to the variable INPUT_FILE.

 **Check if the Input File Exists**

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

```
This checks if the input file exists. If not, it prints an error message and exits.

 **Process Each Line of the Input File**

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

```
- IFS=';' read -r username groups reads each line of the input file, splitting the line into username and groups using ; as a delimiter.
- xargs is used to trim leading and trailing whitespaces from username and groups.

 **Check if the User Already Exists**

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

```
This checks if the user already exists. If the user exists, it logs a message and skips to the next iteration.

 **Create a Personal Group for the User**

```
    # 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."

```
- groupadd $username creates a new group with the same name as the user.
- $? checks the exit status of the groupadd command. If it's not zero (indicating an error), it logs a failure message and skips to the next iteration.
- If the group is created successfully, it logs a success message.

 Create the User and Add to Personal Group

```
    # 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."

```
- useradd -m -g $username -s /bin/bash $username creates the user with a home directory and assigns the personal group.
- The exit status is checked, and appropriate messages are logged.

 **Create Additional Groups and Add User to Them**

```
    # 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

```
- IFS=',' read -ra group_array <<< "$groups" splits the groups string into an array.
- The script iterates over the array, trims whitespaces, checks if the group is empty, and continues to the next iteration if it is.
- It checks if each group exists using getent group $group. If the group does not exist, it creates it.
- The user is added to the group using usermod -aG $group $username.
Appropriate messages are logged throughout

 **Set Up Home Directory Permissions**

```
    # Set 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 of the user's home directory.
- chown $username:$username /home/$username changes the ownership of the home directory to the user.
- A log message is recorded.

 **Generate Random Password and Store It**

```
    # 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."

```
- password=$(generate_password) generates a random password.
- echo "$username:$password" | chpasswd sets the user's password.
- The password is stored in the password file.
- A log message is recorded.

**Complete the Process**

```
done < "$INPUT_FILE"

log_message "User and group creation process completed."

exit 0

```
- The done statement ends the while loop.
- A log message indicates that the process is complete.
- exit 0 exits the script successfully.

This detailed breakdown should help you understand each part of the script and its function as you run it in your terminal.