Automating user and group management with Bash

RMAG news

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:

Create users and groups
set up home directories with the correct permissions
Generate random passwords for users
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:

Step 1: 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

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

Step 2: 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.